1/* 2 * Broadcom Home Gateway Reference Design 3 * Web Page Configuration Support Routines 4 * 5 * Copyright 2005, Broadcom Corporation 6 * All Rights Reserved. 7 * 8 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 9 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 10 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 11 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 12 * $Id: broadcom.c,v 1.1.1.1 2008/10/15 03:31:22 james26_jang Exp $ 13 */ 14 15#ifdef WEBS 16#include <webs.h> 17#include <uemf.h> 18#include <ej.h> 19#else /* !WEBS */ 20#include <stdio.h> 21#include <stdlib.h> 22#include <string.h> 23#include <ctype.h> 24#include <errno.h> 25#include <unistd.h> 26#include <limits.h> 27#include <sys/types.h> 28#include <sys/stat.h> 29#include <sys/socket.h> 30#include <netinet/in.h> 31#include <arpa/inet.h> 32#include <assert.h> 33#include <httpd.h> 34#endif /* WEBS */ 35 36 37/* Required for hash table headers*/ 38#if defined(linux) 39/* Use SVID search */ 40#define __USE_GNU 41#include <search.h> 42#endif 43 44#include <typedefs.h> 45#include <proto/ethernet.h> 46#include <bcmparams.h> 47#include <bcmnvram.h> 48#include <bcmutils.h> 49#include <shutils.h> 50#include <netconf.h> 51#include <nvparse.h> 52#include <wlutils.h> 53#include <bcmcvar.h> 54#include <ezc.h> 55#include <bcmconfig.h> 56#include <opencrypto.h> 57#include <time.h> 58#include <epivers.h> 59 60 61int internal_init(void); 62 63static char * encrypt_var(char *varname, char *ctext, int ctext_len, char *ptext, int *ptext_len,char *key, int keylen); 64static char * decrypt_var(char *varname, char *ptext, int ptext_len, char *ctext, int *ctext_len,char *key, int keylen); 65static char * make_wl_prefix(char *prefix,int prefix_size, int mode, char *ifname); 66static char * remove_dups(char *inlist, int inlist_size); 67static char * rfctime(const time_t *timep); 68static char * reltime(unsigned int seconds); 69static bool find_ethaddr_in_list (void *ethaddr, struct maclist *list); 70 71#define wan_prefix(unit, prefix) snprintf(prefix, sizeof(prefix), "wan%d_", unit) 72 73/* 74 * Country names and abbreviations from ISO 3166 75 */ 76typedef struct { 77 char *name; /* Long name */ 78 char *abbrev; /* Abbreviation */ 79} country_name_t; 80country_name_t country_names[]; /* At end of this file */ 81 82struct variable variables[]; 83extern struct nvram_tuple router_defaults[]; 84 85enum { 86 NOTHING, 87 REBOOT, 88 RESTART, 89}; 90 91static const char * const apply_header = 92"<head>" 93"<title>Broadcom Home Gateway Reference Design: Apply</title>" 94"<meta http-equiv=\"Content-Type\" content=\"application/html; charset=utf-8\">" 95"<style type=\"text/css\">" 96"body { background: white; color: black; font-family: arial, sans-serif; font-size: 9pt }" 97".title { font-family: arial, sans-serif; font-size: 13pt; font-weight: bold }" 98".subtitle { font-family: arial, sans-serif; font-size: 11pt }" 99".label { color: #306498; font-family: arial, sans-serif; font-size: 7pt }" 100"</style>" 101"</head>" 102"<body>" 103"<p>" 104"<span class=\"title\">APPLY</span><br>" 105"<span class=\"subtitle\">This screen notifies you of any errors " 106"that were detected while changing the router's settings.</span>" 107"<form method=\"get\" action=\"apply.cgi\">" 108"<p>" 109; 110 111static const char * const apply_footer = 112"<p>" 113"<input type=\"button\" name=\"action\" value=\"Continue\" OnClick=\"document.location.href='%s';\">" 114"</form>" 115"<p class=\"label\">©2001-2005 Broadcom Corporation. All rights reserved.</p>" 116"</body>" 117; 118 119static int ret_code; 120static char posterr_msg[255]; 121static int action = NOTHING; 122 123#define ERR_MSG_SIZE sizeof(posterr_msg) 124#if defined(linux) 125 126#include <fcntl.h> 127#include <signal.h> 128#include <time.h> 129#include <sys/klog.h> 130#include <sys/wait.h> 131#include <sys/ioctl.h> 132#include <net/if.h> 133 134typedef u_int64_t u64; 135typedef u_int32_t u32; 136typedef u_int16_t u16; 137typedef u_int8_t u8; 138#include <linux/ethtool.h> 139#include <linux/sockios.h> 140#include <net/if_arp.h> 141 142#define sys_restart() kill(1, SIGHUP) 143#define sys_reboot() kill(1, SIGTERM) 144#define sys_stats(url) eval("stats", (url)) 145 146#ifndef WEBS 147 148#define MIN_BUF_SIZE 4096 149 150/* Upgrade from remote server or socket stream */ 151static int 152sys_upgrade(char *url, FILE *stream, int *total) 153{ 154 char upload_fifo[] = "/tmp/uploadXXXXXX"; 155 FILE *fifo = NULL; 156 char *write_argv[] = { "write", upload_fifo, "linux", NULL }; 157 pid_t pid; 158 char *buf = NULL; 159 int count, ret = 0; 160 long flags = -1; 161 int size = BUFSIZ; 162 163 assert(stream); 164 assert(total); 165 166 if (url) 167 return eval("write", url, "linux"); 168 169 /* Feed write from a temporary FIFO */ 170 if (!mktemp(upload_fifo) || 171 mkfifo(upload_fifo, S_IRWXU) < 0|| 172 (ret = _eval(write_argv, NULL, 0, &pid)) || 173 !(fifo = fopen(upload_fifo, "w"))) { 174 if (!ret) 175 ret = errno; 176 goto err; 177 } 178 179 /* Set nonblock on the socket so we can timeout */ 180 if ((flags = fcntl(fileno(stream), F_GETFL)) < 0 || 181 fcntl(fileno(stream), F_SETFL, flags | O_NONBLOCK) < 0) { 182 ret = errno; 183 goto err; 184 } 185 186 /* 187 * The buffer must be at least as big as what the stream file is 188 * using so that it can read all the data that has been buffered 189 * in the stream file. Otherwise it would be out of sync with fn 190 * select specially at the end of the data stream in which case 191 * the select tells there is no more data available but there in 192 * fact is data buffered in the stream file's buffer. Since no 193 * one has changed the default stream file's buffer size, let's 194 * use the constant BUFSIZ until someone changes it. 195 */ 196 if (size < MIN_BUF_SIZE) 197 size = MIN_BUF_SIZE; 198 if ((buf = malloc(size)) == NULL) { 199 ret = ENOMEM; 200 goto err; 201 } 202 203 /* Pipe the rest to the FIFO */ 204 cprintf("Upgrading.\n"); 205 while (total && *total) { 206 if (waitfor(fileno(stream), 5) <= 0) 207 break; 208 count = safe_fread(buf, 1, size, stream); 209 if (!count && (ferror(stream) || feof(stream))) 210 break; 211 *total -= count; 212 safe_fwrite(buf, 1, count, fifo); 213 cprintf("."); 214 } 215 fclose(fifo); 216 fifo = NULL; 217 218 /* Wait for write to terminate */ 219 waitpid(pid, &ret, 0); 220 cprintf("done\n"); 221 222 /* Reset nonblock on the socket */ 223 if (fcntl(fileno(stream), F_SETFL, flags) < 0) { 224 ret = errno; 225 goto err; 226 } 227 228 err: 229 if (buf) 230 free(buf); 231 if (fifo) 232 fclose(fifo); 233 unlink(upload_fifo); 234 return ret; 235} 236 237#endif /* WEBS */ 238 239/* Dump firewall log */ 240static int 241ej_dumplog(int eid, webs_t wp, int argc, char_t **argv) 242{ 243 char buf[4096], *line, *next, *s; 244 int len, ret = 0; 245 246 time_t tm; 247 char *verdict, *src, *dst, *proto, *spt, *dpt; 248 249 if (klogctl(3, buf, 4096) < 0) { 250 websError(wp, 400, "Insufficient memory\n"); 251 return -1; 252 } 253 254 for (next = buf; (line = strsep(&next, "\n"));) { 255 if (!strncmp(line, "<4>DROP", 7)) 256 verdict = "denied"; 257 else if (!strncmp(line, "<4>ACCEPT", 9)) 258 verdict = "accepted"; 259 else 260 continue; 261 262 /* Parse into tokens */ 263 s = line; 264 len = strlen(s); 265 while (strsep(&s, " ")); 266 267 /* Initialize token values */ 268 time(&tm); 269 src = dst = proto = spt = dpt = "n/a"; 270 271 /* Set token values */ 272 for (s = line; s < &line[len] && *s; s += strlen(s) + 1) { 273 if (!strncmp(s, "TIME=", 5)) 274 tm = strtoul(&s[5], NULL, 10); 275 else if (!strncmp(s, "SRC=", 4)) 276 src = &s[4]; 277 else if (!strncmp(s, "DST=", 4)) 278 dst = &s[4]; 279 else if (!strncmp(s, "PROTO=", 6)) 280 proto = &s[6]; 281 else if (!strncmp(s, "SPT=", 4)) 282 spt = &s[4]; 283 else if (!strncmp(s, "DPT=", 4)) 284 dpt = &s[4]; 285 } 286 287 ret += websWrite(wp, "%s %s connection %s to %s:%s from %s:%s\n", 288 rfctime(&tm), proto, verdict, dst, dpt, src, spt); 289 ret += websWrite(wp, "<br>"); 290 } 291 292 return ret; 293} 294 295static int 296ej_syslog(int eid, webs_t wp, int argc, char_t **argv) 297{ 298 FILE *fp; 299 char buf[256] = "/sbin/logread > "; 300 char tmp[] = "/tmp/log.XXXXXX"; 301 int ret; 302 303 if (!nvram_match("log_ram_enable", "1")) { 304 websError(wp, 400, "\"Syslog in RAM\" is not enabled.\n"); 305 return (-1); 306 } 307 308 mktemp(tmp); 309 strcat(buf, tmp); 310 system(buf); 311 312 fp = fopen(tmp, "r"); 313 314 unlink(tmp); 315 316 if (fp == NULL) { 317 websError(wp, 400, "logread error\n"); 318 return (-1); 319 } 320 321 websWrite(wp, "<pre>"); 322 323 ret = 0; 324 while(fgets(buf, sizeof(buf), fp)) 325 ret += websWrite(wp, buf); 326 327 ret += websWrite(wp, "</pre>"); 328 329 fclose(fp); 330 331 return (ret); 332} 333 334struct lease_t { 335 unsigned char chaddr[16]; 336 u_int32_t yiaddr; 337 u_int32_t expires; 338 char hostname[64]; 339}; 340 341/* Dump leases in <tr><td>hostname</td><td>MAC</td><td>IP</td><td>expires</td></tr> format */ 342static int 343ej_lan_leases(int eid, webs_t wp, int argc, char_t **argv) 344{ 345 FILE *fp = NULL; 346 struct lease_t lease; 347 int i; 348 int index,num_interfaces=0; 349 char buf[128]; 350 struct in_addr addr; 351 unsigned long expires = 0; 352 char sigusr1[] = "-XX"; 353 int ret = 0; 354 char word[32], *next = NULL; 355 356 /* Write out leases file */ 357 sprintf(sigusr1, "-%d", SIGUSR1); 358 eval("killall", sigusr1, "udhcpd"); 359 360 /* Count the number of lan and guest interfaces */ 361 362 if (nvram_get("lan_ifname")) 363 num_interfaces++; 364 365 if (nvram_get("unbridged_ifnames")) 366 foreach(word,nvram_get("unbridged_ifnames"),next) 367 num_interfaces++; 368 369 for (index =0; index < num_interfaces; index++){ 370 snprintf(buf,sizeof(buf),"/tmp/udhcpd%d.leases",index); 371 372 if (!(fp = fopen(buf, "r"))) 373 continue; 374 375 while (fread(&lease, sizeof(lease), 1, fp)) { 376 /* Do not display reserved leases */ 377 if (ETHER_ISNULLADDR(lease.chaddr)) 378 continue; 379 ret += websWrite(wp, "<tr><td>%s</td><td>", lease.hostname); 380 for (i = 0; i < 6; i++) { 381 ret += websWrite(wp, "%02X", lease.chaddr[i]); 382 if (i != 5) ret += websWrite(wp, ":"); 383 } 384 addr.s_addr = lease.yiaddr; 385 ret += websWrite(wp, "</td><td>%s</td><td>", inet_ntoa(addr)); 386 expires = ntohl(lease.expires); 387 if (!expires) 388 ret += websWrite(wp, "Expired"); 389 else 390 ret += websWrite(wp, "%s", reltime(expires)); 391 ret += websWrite(wp, "</td></tr>"); 392 } 393 394 fclose(fp); 395 } 396 397 return ret; 398} 399 400/* Renew lease */ 401static int 402sys_renew(void) 403{ 404 int unit; 405 char tmp[NVRAM_BUFSIZE]; 406 char *str = NULL; 407 int pid; 408 409 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 410 unit = 0; 411 412 snprintf(tmp, sizeof(tmp), "/var/run/udhcpc%d.pid", unit); 413 if ((str = file2str(tmp))) { 414 pid = atoi(str); 415 free(str); 416 return kill(pid, SIGUSR1); 417 } 418 419 return -1; 420} 421 422/* Release lease */ 423static int 424sys_release(void) 425{ 426 int unit; 427 char tmp[NVRAM_BUFSIZE]; 428 char *str= NULL; 429 int pid; 430 431 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 432 unit = 0; 433 434 snprintf(tmp, sizeof(tmp), "/var/run/udhcpc%d.pid", unit); 435 if ((str = file2str(tmp))) { 436 pid = atoi(str); 437 free(str); 438 return kill(pid, SIGUSR2); 439 } 440 441 return -1; 442} 443 444#ifdef __CONFIG_NAT__ 445#define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr) 446 447/* Return WAN link state */ 448static int 449ej_wan_link(int eid, webs_t wp, int argc, char_t **argv) 450{ 451 char *wan_ifname; 452 int s; 453 struct ifreq ifr; 454 struct ethtool_cmd ecmd; 455 FILE *fp= NULL; 456 int unit; 457 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 458 459 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 460 unit = 0; 461 wan_prefix(unit, prefix); 462 463 /* non-exist and disabled */ 464 if (nvram_match(strcat_r(prefix, "proto", tmp), "") || 465 nvram_match(strcat_r(prefix, "proto", tmp), "disabled")) { 466 return websWrite(wp, "N/A"); 467 } 468 /* PPPoE connection status */ 469 else if (nvram_match(strcat_r(prefix, "proto", tmp), "pppoe")) { 470 wan_ifname = nvram_safe_get(strcat_r(prefix, "pppoe_ifname", tmp)); 471 if ((fp = fopen(strcat_r("/tmp/ppp/link.", wan_ifname, tmp), "r"))) { 472 fclose(fp); 473 return websWrite(wp, "Connected"); 474 } else 475 return websWrite(wp, "Disconnected"); 476 } 477 /* Get real interface name */ 478 else 479 wan_ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 480 481 /* Open socket to kernel */ 482 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 483 return websWrite(wp, "N/A"); 484 485 /* Check for hardware link */ 486 strncpy(ifr.ifr_name, wan_ifname, IFNAMSIZ); 487 ifr.ifr_data = (void *) &ecmd; 488 ecmd.cmd = ETHTOOL_GSET; 489 if (ioctl(s, SIOCETHTOOL, &ifr) < 0) { 490 close(s); 491 return websWrite(wp, "Unknown"); 492 } 493 if (!ecmd.speed) { 494 close(s); 495 return websWrite(wp, "Disconnected"); 496 } 497 498 /* Check for valid IP address */ 499 strncpy(ifr.ifr_name, wan_ifname, IFNAMSIZ); 500 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { 501 close(s); 502 return websWrite(wp, "Connecting"); 503 } 504 505 /* Otherwise we are probably configured */ 506 close(s); 507 return websWrite(wp, "Connected"); 508} 509 510/* Display IP Address lease */ 511static int 512ej_wan_lease(int eid, webs_t wp, int argc, char_t **argv) 513{ 514 unsigned long expires = 0; 515 int ret = 0; 516 int unit; 517 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 518 519 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 520 unit = 0; 521 wan_prefix(unit, prefix); 522 523 if (nvram_match(strcat_r(prefix, "proto", tmp), "dhcp")) { 524 char *str; 525 time_t now; 526 527 snprintf(tmp, sizeof(tmp), "/tmp/udhcpc%d.expires", unit); 528 if ((str = file2str(tmp))) { 529 expires = atoi(str); 530 free(str); 531 } 532 time(&now); 533 if (expires <= now) 534 ret += websWrite(wp, "Expired"); 535 else 536 ret += websWrite(wp, "%s", reltime(expires - now)); 537 } else 538 ret += websWrite(wp, "N/A"); 539 540 return ret; 541} 542#endif /* __CONFIG_NAT__ */ 543 544/* Report sys up time */ 545static int 546ej_sysuptime(int eid, webs_t wp, int argc, char_t **argv) 547{ 548 char *str = file2str("/proc/uptime"); 549 if (str) { 550 unsigned int up = atoi(str); 551 free(str); 552 return websWrite(wp, reltime(up)); 553 } 554 return websWrite(wp, "N/A"); 555} 556 557#ifdef __CONFIG_NAT__ 558/* Return a list of wan interfaces (eth0/eth1/eth2/eth3) */ 559static int 560ej_wan_iflist(int eid, webs_t wp, int argc, char_t **argv) 561{ 562 char name[IFNAMSIZ], *next; 563 int ret = 0; 564 int unit; 565 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 566 char ea[64]; 567 int s; 568 struct ifreq ifr; 569 570 /* current unit # */ 571 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 572 unit = 0; 573 wan_prefix(unit, prefix); 574 575 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 576 return errno; 577 578 /* build wan interface name list */ 579 foreach(name, nvram_safe_get("wan_ifnames"), next) { 580 strncpy(ifr.ifr_name, name, IFNAMSIZ); 581 if (ioctl(s, SIOCGIFHWADDR, &ifr)) 582 continue; 583 ret += websWrite(wp, "<option value=\"%s\" %s>%s (%s)</option>", name, 584 nvram_match(strcat_r(prefix, "ifname", tmp), name) ? "selected" : "", 585 name, ether_etoa(ifr.ifr_hwaddr.sa_data, ea)); 586 } 587 588 close(s); 589 590 return ret; 591} 592#endif /* __CONFIG_NAT__ */ 593 594 595#endif /* vxworks */ 596 597static int 598ej_lan_guest_iflist(int eid, webs_t wp, int argc, char_t **argv) 599{ 600 int ret = 0; 601 char ifnames[255],name[IFNAMSIZ],os_name[IFNAMSIZ],*next=NULL; 602 char buf[32],*config_num, *value=NULL; 603 604 if (ejArgs(argc, argv, "%s", &config_num) < 1) { 605 websError(wp, 400, "Insufficient args\n"); 606 return -1; 607 } 608 609 /* Do some of the housekeeping here to remove any leftover invalid NVRAM vars 610 prior to display */ 611 612 snprintf(ifnames, sizeof(ifnames), "%s", nvram_safe_get("unbridged_ifnames")); 613 614 snprintf(buf, sizeof(buf), "lan%s_ifname", config_num); 615 616 value = nvram_safe_get(buf); 617 618 619 if (!*ifnames) 620 { 621 ret += websWrite(wp, "<option value=\"NONE\" selected >NONE</option>"); 622 return ret; 623 } 624 625 if (!remove_dups(ifnames,sizeof(ifnames))){ 626 websError(wp, 400, "Unable to remove duplicate interfaces from ifname list<br>"); 627 return -1; 628 } 629 630 foreach(name, ifnames, next) { 631 632 633 if (nvifname_to_osifname( name, os_name, sizeof(os_name) ) < 0) 634 continue; 635 636 ret += websWrite(wp, "<option value=\"%s\"%s>%s%s</option>", 637 name, strcmp(name,value) ? "":" selected ", 638 name, !wl_probe(os_name) ? " (Wireless)" : ""); 639 } 640 641 ret += websWrite(wp, "<option value=\"NONE\"%s>NONE</option>",(*value) ? "" : " selected "); 642 643 return ret; 644} 645static int 646ej_asp_list(int eid, webs_t wp, int argc, char_t **argv) 647{ 648 websWrite(wp, 649 "<tr>\n" 650 " <td><a href=\"index.asp\"><img border=\"0\" src=\"basic.gif\" alt=\"Basic\"></a></td>\n" 651 " <td><a href=\"lan.asp\"><img border=\"0\" src=\"lan.gif\" alt=\"LAN\"></a></td>\n"); 652#ifdef __CONFIG_NAT__ 653 websWrite(wp, 654 " <td><a href=\"wan.asp\"><img border=\"0\" src=\"wan.gif\" alt=\"WAN\"></a></td>\n"); 655#endif 656 websWrite(wp, 657 " <td><a href=\"status.asp\"><img border=\"0\" src=\"status.gif\" alt=\"Status\"></a></td>\n"); 658#ifdef __CONFIG_NAT__ 659 websWrite(wp, 660 " <td><a href=\"filter.asp\"><img border=\"0\" src=\"filter.gif\" alt=\"Filters\"></a></td>\n" 661 " <td><a href=\"forward.asp\"><img border=\"0\" src=\"forward.gif\" alt=\"Routing\"></a></td>\n"); 662#endif 663 websWrite(wp, 664 " <td><a href=\"wireless.asp\"><img border=\"0\" src=\"wireless.gif\" alt=\"Wireless\"></a></td>\n" 665 " <td><a href=\"security.asp\"><img border=\"0\" src=\"security.gif\" alt=\"Security\"></a></td>\n" 666 " <td><a href=\"firmware.asp\"><img border=\"0\" src=\"firmware.gif\" alt=\"Firmware\"></a></td>\n"); 667 websWrite(wp, 668 " <td width=\"100%%\"></td>\n" 669 "</tr>\n"); 670 return 0; 671} 672 673static char * 674rfctime(const time_t *timep) 675{ 676 static char s[201]; 677 struct tm tm; 678 679#if defined(linux) 680 setenv("TZ", nvram_safe_get("time_zone"), 1); 681#endif 682 memcpy(&tm, localtime(timep), sizeof(struct tm)); 683 strftime(s, 200, "%a, %d %b %Y %H:%M:%S %z", &tm); 684 return s; 685} 686 687static char * 688reltime(unsigned int seconds) 689{ 690 static char s[] = "XXXXX days, XX hours, XX minutes, XX seconds"; 691 char *c = s; 692 693 if (seconds > 60*60*24) { 694 c += sprintf(c, "%d days, ", seconds / (60*60*24)); 695 seconds %= 60*60*24; 696 } 697 if (seconds > 60*60) { 698 c += sprintf(c, "%d hours, ", seconds / (60*60)); 699 seconds %= 60*60; 700 } 701 if (seconds > 60) { 702 c += sprintf(c, "%d minutes, ", seconds / 60); 703 seconds %= 60; 704 } 705 c += sprintf(c, "%d seconds", seconds); 706 707 return s; 708} 709 710/* Report time in RFC-822 format */ 711static int 712ej_localtime(int eid, webs_t wp, int argc, char_t **argv) 713{ 714 time_t tm; 715 716 time(&tm); 717 return websWrite(wp, rfctime(&tm)); 718} 719 720static int 721ej_wl_mode_list(int eid, webs_t wp, int argc, char_t **argv) 722{ 723 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 724 char wl_mode[]="wlXXXXXXXXXX_mode"; 725 char *name=NULL, *next=NULL; 726 int ap = 0, sta = 0, wet = 0, wds = 0; 727 char cap[WLC_IOCTL_SMLEN]; 728 char caps[WLC_IOCTL_SMLEN]; 729 730 731 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 732 websError(wp, 400, "unit number variable doesn't exist\n"); 733 return -1; 734 } 735 736 snprintf(wl_mode,sizeof(wl_mode),"%smode",prefix); 737 738 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 739 740 if (wl_iovar_get(name, "cap", (void *)caps, WLC_IOCTL_SMLEN)) 741 return -1; 742 743 foreach(cap, caps, next) { 744 if (!strcmp(cap, "ap")) 745 ap = wds = 1; 746 else if (!strcmp(cap, "sta")) 747 sta = 1; 748 else if (!strcmp(cap, "wet")) 749 wet = 1; 750 } 751 752 if (ap) 753 websWrite(wp, "<option value=\"ap\" %s>Access Point</option>\n", 754 nvram_match(wl_mode, "ap" ) ? "selected" : ""); 755 if (wds) 756 websWrite(wp, "<option value=\"wds\" %s>Wireless Bridge</option>\n", 757 nvram_match(wl_mode, "wds" ) ? "selected" : ""); 758 if (wet) 759 websWrite(wp, "<option value=\"wet\" %s>Wireless Ethernet</option>\n", 760 nvram_match(wl_mode, "wet" ) ? "selected" : ""); 761 return 0; 762} 763 764static int 765ej_wl_guest_ssid(int eid, webs_t wp, int argc, char_t **argv) 766{ 767 768 char *bss_config_num=NULL,*ssid=NULL; 769 char vif[64],*unit=NULL; 770 771 if (ejArgs(argc, argv, "%s", &bss_config_num) < 1) { 772 websError(wp, 400, "Insufficient args\n"); 773 return -1; 774 } 775 776 777 unit = nvram_get("wl_unit"); 778 if (!unit){ 779 websError(wp, 400, "unit number variable doesn't exist\n"); 780 return -1; 781 } 782 783 snprintf(vif,sizeof(vif),"wl%s.%s_ssid",unit,bss_config_num); 784 785 ssid = nvram_get(vif); 786 787 return (ssid ? websWrite(wp, "%s", ssid): 0); 788} 789static int 790ej_wl_inlist(int eid, webs_t wp, int argc, char_t **argv) 791{ 792 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 793 char *name=NULL, *next=NULL; 794 char cap[WLC_IOCTL_SMLEN]; 795 char caps[WLC_IOCTL_SMLEN]; 796 char *var=NULL, *item=NULL; 797 798 if (ejArgs(argc, argv, "%s %s", &var, &item) < 2) { 799 websError(wp, 400, "Insufficient args\n"); 800 return -1; 801 } 802 803 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 804 websError(wp, 400, "unit number variable doesn't exist\n"); 805 return -1; 806 } 807 808 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 809 810 if (wl_iovar_get(name, var, (void *)caps, WLC_IOCTL_SMLEN)) 811 return -1; 812 813 foreach(cap, caps, next) { 814 if (!strcmp(cap, item)) 815 return websWrite(wp, "1"); 816 } 817 818 return websWrite(wp, "0"); 819} 820 821static int 822ej_wl_wds_status(int eid, webs_t wp, int argc, char_t **argv) 823{ 824 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 825 char *macs=NULL, *next=NULL, *name=NULL; 826 char mac[100]; 827 int i=0, len=0; 828 sta_info_t *sta=NULL; 829 char buf[300]; 830 831 if (ejArgs(argc, argv, "%d", &i) < 1) { 832 websError(wp, 400, "Insufficient args\n"); 833 return -1; 834 } 835 836 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 837 websError(wp, 400, "Insufficient args\n"); 838 return -1; 839 } 840 841 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 842 macs = nvram_safe_get(strcat_r(prefix, "wds", tmp)); 843 844 foreach(mac, macs, next) { 845 if (i-- == 0) { 846 len = sprintf(buf, "sta_info"); 847 ether_atoe(mac, (unsigned char *)&buf[len + 1]); 848 if (atoi(nvram_safe_get(strcat_r(prefix, "wds_timeout", tmp))) && 849 !wl_ioctl(name, WLC_GET_VAR, buf, sizeof(buf))) { 850 sta = (sta_info_t *)buf; 851 return websWrite(wp, "%s", (sta->flags & WL_WDS_LINKUP) ? "up" : "down"); 852 } 853 else 854 return websWrite(wp, "%s", "unknown"); 855 } 856 } 857 858 return 0; 859} 860 861static int 862ej_ses_button_display(int eid, webs_t wp, int argc, char_t **argv) 863{ 864 865 return 1; 866} 867 868 869static int 870ej_ses_cl_button_display(int eid, webs_t wp, int argc, char_t **argv) 871{ 872 873 return 1; 874} 875static int 876ej_wl_radio_roam_option(int eid, webs_t wp, int argc, char_t **argv) 877{ 878 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 879 char *name=NULL; 880 int radio_status = 0; 881 882 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 883 websError(wp, 400, "unit number variable doesn't exist\n"); 884 return -1; 885 } 886 name = nvram_get(strcat_r(prefix, "ifname", tmp)); 887 888 if (!name){ 889 websError(wp, 400, "Could not find: %s\n",strcat_r(prefix, "ifname", tmp)); 890 return -1; 891 } 892 893 wl_ioctl(name, WLC_GET_RADIO, &radio_status, sizeof (radio_status)); 894 radio_status &= WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE; 895 896 if (!radio_status) /* Radio on*/ 897 websWrite(wp, "<input type=\"submit\" name=\"action\" value=\"RadioOff\" >"); 898 else /* Radio Off */ 899 websWrite(wp, "<input type=\"submit\" name=\"action\" value=\"RadioOn\" >"); 900 901 return 1; 902 903 904} 905static int 906wl_radio_onoff(webs_t wp, int disable) 907{ 908 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 909 char *name=NULL; 910 char *interface_status=NULL; 911 uint radiomaskval = 0; 912 913 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 914 websError(wp, 400, "unit number variable doesn't exist\n"); 915 return -1; 916 } 917 918 interface_status = nvram_get(strcat_r(prefix, "radio", tmp)); 919 920 if (interface_status != NULL) { 921 if (!strcmp(interface_status, "1")) { 922 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 923 radiomaskval = WL_RADIO_SW_DISABLE << 16 | disable; 924 wl_ioctl(name, WLC_SET_RADIO, &radiomaskval, sizeof (disable)); 925 } 926 else { 927 websWrite(wp, "Interface is not Enabled..."); 928 return 0; 929 } 930 } 931 else { 932 websWrite(wp, "Interface status UnKnown..."); 933 return 0; 934 } 935 936 937 return 0; 938 939} 940 941/* 942 * Example: 943 * lan_ipaddr=192.168.1.1 944 * <% nvram_get("lan_ipaddr"); %> produces "192.168.1.1" 945 * <% nvram_get("undefined"); %> produces "" 946 */ 947static int 948ej_nvram_get(int eid, webs_t wp, int argc, char_t **argv) 949{ 950 char *name=NULL, *c=NULL; 951 int ret = 0; 952 953 if (ejArgs(argc, argv, "%s", &name) < 1) { 954 websError(wp, 400, "Insufficient args\n"); 955 return -1; 956 } 957 958 assert(name); 959 960 for (c = nvram_safe_get(name); *c; c++) { 961 if (isprint((int) *c) && 962 *c != '"' && *c != '&' && *c != '<' && *c != '>') 963 ret += websWrite(wp, "%c", *c); 964 else 965 ret += websWrite(wp, "&#%d", *c); 966 } 967 968 return ret; 969} 970 971/* 972 * Example: 973 * wan_proto=dhcp 974 * <% nvram_match("wan_proto", "dhcp", "selected"); %> produces "selected" 975 * <% nvram_match("wan_proto", "static", "selected"); %> does not produce 976 */ 977static int 978ej_nvram_match(int eid, webs_t wp, int argc, char_t **argv) 979{ 980 char *name=NULL, *match=NULL, *output=NULL; 981 982 if (ejArgs(argc, argv, "%s %s %s", &name, &match, &output) < 3) { 983 websError(wp, 400, "Insufficient args\n"); 984 return -1; 985 } 986 987 assert(name); 988 assert(match); 989 assert(output); 990 991 if (nvram_match(name, match)) 992 return websWrite(wp, output); 993 994 return 0; 995} 996 997static int 998ej_wme_match_op(int eid, webs_t wp, int argc, char_t **argv) 999{ 1000 char *name=NULL, *match=NULL, *output=NULL; 1001 char word[256], *next=NULL; 1002 1003 if (ejArgs(argc, argv, "%s %s %s", &name, &match, &output) < 3) { 1004 websError(wp, 400, "Insufficient args\n"); 1005 return -1; 1006 } 1007 1008 assert(name); 1009 assert(match); 1010 assert(output); 1011 1012 foreach(word, nvram_safe_get(name), next) { 1013 if (!strcmp(word, match)) 1014 return websWrite(wp, output); 1015 } 1016 1017 return 0; 1018} 1019 1020static int 1021wl_print_channel_list(webs_t wp, char *name, char *phytype, char *abbrev) 1022{ 1023 int j, status = 0; 1024 wl_channels_in_country_t *cic = (wl_channels_in_country_t *)malloc(WLC_IOCTL_MAXLEN); 1025 1026 assert(name); 1027 assert(phytype); 1028 assert(abbrev); 1029 1030 if (!cic) { 1031 status = -1; 1032 goto exit; 1033 } 1034 1035 cic->buflen = WLC_IOCTL_MAXLEN; 1036 strcpy(cic->country_abbrev, abbrev); 1037 if (!strcmp(phytype, "a")) 1038 cic->band = WLC_BAND_A; 1039 else if ((!strcmp(phytype, "b")) || (!strcmp(phytype, "g"))) 1040 cic->band = WLC_BAND_B; 1041 else { 1042 status = -1; 1043 goto exit; 1044 } 1045 1046 if (wl_ioctl(name, WLC_GET_CHANNELS_IN_COUNTRY, cic, cic->buflen) == 0) { 1047 if (cic->count == 0) { 1048 status = 0; 1049 goto exit; 1050 } 1051 websWrite(wp, "\t\tif (country == \"%s\")\n\t\t\tchannels = new Array(0", 1052 abbrev); 1053 for(j = 0; j < cic->count; j++) 1054 websWrite(wp, ", %d", cic->channel[j]); 1055 websWrite(wp,");\n"); 1056 } 1057 1058exit: 1059 if (cic) 1060 free((void *)cic); 1061 return status; 1062} 1063 1064static int 1065ej_wl_country_list(int eid, webs_t wp, int argc, char_t **argv) 1066{ 1067 int i =0, status = 0; 1068 char *name =NULL; 1069 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1070 char *phytype = NULL; 1071 wl_country_list_t *cl = (wl_country_list_t *)malloc(WLC_IOCTL_MAXLEN); 1072 country_name_t *cntry=NULL; 1073 char *abbrev=NULL; 1074 1075 if (!cl) { 1076 status = -1; 1077 goto exit; 1078 } 1079 1080 if (ejArgs(argc, argv, "%s", &phytype) < 1) { 1081 websError(wp, 400, "Insufficient args\n"); 1082 status = -1; 1083 goto exit; 1084 } 1085 1086 assert(phytype); 1087 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 1088 websError(wp, 400, "unit number variable doesn't exist\n"); 1089 status = -1; 1090 goto exit; 1091 } 1092 1093 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1094 1095 cl->buflen = WLC_IOCTL_MAXLEN; 1096 cl->band_set = TRUE; 1097 1098 if (!strcmp(phytype, "a")) 1099 cl->band = WLC_BAND_A; 1100 else if ((!strcmp(phytype, "b")) || (!strcmp(phytype, "g"))) 1101 cl->band = WLC_BAND_B; 1102 else { 1103 status = -1; 1104 goto exit; 1105 } 1106 1107 if (wl_ioctl(name, WLC_GET_COUNTRY_LIST, cl, cl->buflen) == 0) { 1108 websWrite(wp, "\t\tvar countries = new Array("); 1109 for(i = 0; i < cl->count; i++) { 1110 abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ]; 1111 websWrite(wp, "\"%s\"", abbrev); 1112 if (i != (cl->count - 1)) 1113 websWrite(wp, ", "); 1114 } 1115 websWrite(wp, ");\n"); 1116 for(i = 0; i < cl->count; i++) { 1117 abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ]; 1118 for(cntry = country_names; 1119 cntry->name && strcmp(abbrev, cntry->abbrev); 1120 cntry++); 1121 websWrite(wp, "\t\tdocument.forms[0].wl_country_code[%d] = new Option(\"%s\", \"%s\");\n", 1122 i, cntry->name ? cntry->name : abbrev, abbrev); 1123 } 1124 } 1125 1126exit: 1127 if (cl) 1128 free((void *)cl); 1129 return status; 1130} 1131 1132static int 1133ej_wl_channel_list(int eid, webs_t wp, int argc, char_t **argv) 1134{ 1135 int i, status = 0; 1136 char *name=NULL; 1137 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1138 char *phytype = NULL; 1139 wl_country_list_t *cl = (wl_country_list_t *)malloc(WLC_IOCTL_MAXLEN); 1140 char *abbrev=NULL; 1141 1142 if (!cl) { 1143 status = -1; 1144 goto exit; 1145 } 1146 1147 if (ejArgs(argc, argv, "%s", &phytype) < 1) { 1148 websError(wp, 400, "Insufficient args\n"); 1149 status = -1; 1150 goto exit; 1151 } 1152 1153 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 1154 websError(wp, 400, "unit number variable doesn't exist\n"); 1155 status = -1; 1156 goto exit; 1157 } 1158 1159 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1160 1161 cl->buflen = WLC_IOCTL_MAXLEN; 1162 cl->band_set = TRUE; 1163 1164 if (!strcmp(phytype, "a")) 1165 cl->band = WLC_BAND_A; 1166 else if ((!strcmp(phytype, "b")) || (!strcmp(phytype, "g"))) 1167 cl->band = WLC_BAND_B; 1168 else { 1169 status = -1; 1170 goto exit; 1171 } 1172 1173 if (wl_ioctl(name, WLC_GET_COUNTRY_LIST, cl, cl->buflen) == 0) { 1174 for(i = 0; i < cl->count; i++) { 1175 abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ]; 1176 wl_print_channel_list(wp, name, phytype, abbrev); 1177 } 1178 } 1179 1180 1181exit: 1182 if (cl) 1183 free((void *)cl); 1184 return status; 1185} 1186 1187static bool find_ethaddr_in_list (void *ethaddr, struct maclist *list) 1188{ 1189 int i=0; 1190 1191 assert(ethaddr); 1192 assert(list); 1193 1194 for (i = 0; i < list->count; i ++) { 1195 if (!bcmp(ethaddr, (void *)&list->ea[i], ETHER_ADDR_LEN)) { 1196 return TRUE; 1197 } 1198 } 1199 1200 return FALSE; 1201} 1202 1203static int 1204ej_wl_auth_list(int eid, webs_t wp, int argc, char_t **argv) 1205{ 1206 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1207 char *name=NULL; 1208 struct maclist *auth=NULL, *assoc=NULL, *authorized=NULL, *wme=NULL; 1209 int max_sta_count, maclist_size; 1210 int i=0; 1211 1212 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) { 1213 websError(wp, 400, "unit number variable doesn't exist\n"); 1214 return -1; 1215 } 1216 1217 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1218 1219 /* buffers and length */ 1220 max_sta_count = MAX_STA_COUNT; 1221 maclist_size = sizeof(auth->count) + max_sta_count * sizeof(struct ether_addr); 1222 1223 auth = malloc(maclist_size); 1224 assoc = malloc(maclist_size); 1225 authorized = malloc(maclist_size); 1226 wme = malloc(maclist_size); 1227 1228 if (!auth || !assoc || !authorized || !wme) 1229 goto exit; 1230 1231 /* query wl for authenticated sta list */ 1232 strcpy((char*)auth, "authe_sta_list"); 1233 if (wl_ioctl(name, WLC_GET_VAR, auth, maclist_size)) 1234 goto exit; 1235 1236 /* query wl for associated sta list */ 1237 assoc->count = max_sta_count; 1238 if (wl_ioctl(name, WLC_GET_ASSOCLIST, assoc, maclist_size)) 1239 goto exit; 1240 1241 /* query wl for authorized sta list */ 1242 strcpy((char*)authorized, "autho_sta_list"); 1243 if (wl_ioctl(name, WLC_GET_VAR, authorized, maclist_size)) 1244 goto exit; 1245 1246 /* query wl for WME sta list */ 1247 strcpy((char*)wme, "wme_sta_list"); 1248 if (wl_ioctl(name, WLC_GET_VAR, wme, maclist_size)) 1249 goto exit; 1250 1251 /* build authenticated/associated/authorized sta list */ 1252 for (i = 0; i < auth->count; i ++) { 1253 char ea[ETHER_ADDR_STR_LEN]; 1254 char *value; 1255 websWrite(wp, "<tr><td>%s</td>", ether_etoa((void *)&auth->ea[i], ea)); 1256 1257 value = (find_ethaddr_in_list ((void *)&auth->ea[i], assoc))? "Yes" : "No"; 1258 websWrite(wp, "<td>%s</td>", value); 1259 1260 value = (find_ethaddr_in_list ((void *)&auth->ea[i], authorized))? "Yes" : "No"; 1261 websWrite(wp, "<td>%s</td>", value); 1262 1263 value = (find_ethaddr_in_list ((void *)&auth->ea[i], wme))? "Yes" : "No"; 1264 websWrite(wp, "<td>%s</td>", value); 1265 1266 websWrite(wp, "</tr>"); 1267 } 1268 1269 /* error/exit */ 1270exit: 1271 if (auth) free(auth); 1272 if (assoc) free(assoc); 1273 if (authorized) free(authorized); 1274 if (wme) free(wme); 1275 1276 return 0; 1277} 1278 1279/* 1280 * Example: 1281 * wan_proto=dhcp 1282 * <% nvram_invmatch("wan_proto", "dhcp", "disabled"); %> does not produce 1283 * <% nvram_invmatch("wan_proto", "static", "disabled"); %> produces "disabled" 1284 */ 1285static int 1286ej_nvram_invmatch(int eid, webs_t wp, int argc, char_t **argv) 1287{ 1288 char *name=NULL, *invmatch=NULL, *output=NULL; 1289 1290 if (ejArgs(argc, argv, "%s %s %s", &name, &invmatch, &output) < 3) { 1291 websError(wp, 400, "Insufficient args\n"); 1292 return -1; 1293 } 1294 1295 assert(name); 1296 assert(invmatch); 1297 assert(output); 1298 1299 if (nvram_invmatch(name, invmatch)) 1300 return websWrite(wp, output); 1301 1302 return 0; 1303} 1304 1305/* 1306 * Example: 1307 * filter_maclist=00:12:34:56:78:00 00:87:65:43:21:00 1308 * <% nvram_list("filter_maclist", 1); %> produces "00:87:65:43:21:00" 1309 * <% nvram_list("filter_maclist", 100); %> produces "" 1310 */ 1311static int 1312ej_nvram_list(int eid, webs_t wp, int argc, char_t **argv) 1313{ 1314 char *name=NULL; 1315 int which=0; 1316 char word[256], *next=NULL; 1317 1318 if (ejArgs(argc, argv, "%s %d", &name, &which) < 2) { 1319 websError(wp, 400, "Insufficient args\n"); 1320 return -1; 1321 } 1322 1323 foreach(word, nvram_safe_get(name), next) { 1324 if (which-- == 0) 1325 return websWrite(wp, word); 1326 } 1327 1328 return 0; 1329} 1330 1331static int 1332ej_nvram_inlist(int eid, webs_t wp, int argc, char_t **argv) 1333{ 1334 char *name, *item, *output; 1335 char word[256], *next; 1336 1337 if (ejArgs(argc, argv, "%s %s %s", &name, &item, &output) < 3) { 1338 websError(wp, 400, "Insufficient args\n"); 1339 return -1; 1340 } 1341 1342 foreach(word, nvram_safe_get(name), next) { 1343 if (!strcmp(word, item)) 1344 return websWrite(wp, output); 1345 } 1346 1347 return 0; 1348} 1349 1350static int 1351ej_nvram_invinlist(int eid, webs_t wp, int argc, char_t **argv) 1352{ 1353 char *name, *item, *output; 1354 char word[256], *next; 1355 1356 if (ejArgs(argc, argv, "%s %s %s", &name, &item, &output) < 3) { 1357 websError(wp, 400, "Insufficient args\n"); 1358 return -1; 1359 } 1360 1361 foreach(word, nvram_safe_get(name), next) { 1362 if (!strcmp(word, item)) 1363 return 0; 1364 } 1365 1366 return websWrite(wp, output); 1367} 1368 1369#ifdef __CONFIG_NAT__ 1370/* 1371 * Example: 1372 * <% filter_client(1, 10); %> produces a table of the first 10 client filter entries 1373 */ 1374static int 1375ej_filter_client(int eid, webs_t wp, int argc, char_t **argv) 1376{ 1377 int i, n, j, ret = 0; 1378 netconf_filter_t start, end; 1379 bool valid; 1380 char port[] = "XXXXX"; 1381 char *days[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; 1382 char *hours[] = { 1383 "12:00 AM", "1:00 AM", "2:00 AM", "3:00 AM", "4:00 AM", "5:00 AM", 1384 "6:00 AM", "7:00 AM", "8:00 AM", "9:00 AM", "10:00 AM", "11:00 AM", 1385 "12:00 PM", "1:00 PM", "2:00 PM", "3:00 PM", "4:00 PM", "5:00 PM", 1386 "6:00 PM", "7:00 PM", "8:00 PM", "9:00 PM", "10:00 PM", "11:00 PM" 1387 }; 1388 1389 if (ejArgs(argc, argv, "%d %d", &i, &n) < 2) { 1390 websError(wp, 400, "Insufficient args\n"); 1391 return -1; 1392 } 1393 1394 for (; i <= n; i++) { 1395 valid = get_filter_client(i, &start, &end); 1396 1397 ret += websWrite(wp, "<tr>"); 1398 ret += websWrite(wp, "<td></td>"); 1399 1400 /* Print address range */ 1401 ret += websWrite(wp, "<td><input name=\"filter_client_from_start%d\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>", 1402 i, valid ? inet_ntoa(start.match.src.ipaddr) : ""); 1403 ret += websWrite(wp, "<td>-</td>"); 1404 ret += websWrite(wp, "<td><input name=\"filter_client_from_end%d\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>", 1405 i, valid ? inet_ntoa(end.match.src.ipaddr) : ""); 1406 ret += websWrite(wp, "<td></td>"); 1407 1408 /* Print protocol */ 1409 ret += websWrite(wp, "<td>"); 1410 ret += websWrite(wp, "<select name=\"filter_client_proto%d\">", i); 1411 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 1412 valid && start.match.ipproto == IPPROTO_TCP ? "selected" : ""); 1413 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 1414 valid && start.match.ipproto == IPPROTO_UDP ? "selected" : ""); 1415 ret += websWrite(wp, "</select>"); 1416 ret += websWrite(wp, "</td>"); 1417 ret += websWrite(wp, "<td></td>"); 1418 1419 /* Print port range */ 1420 if (valid) 1421 snprintf(port, sizeof(port), "%d", ntohs(start.match.dst.ports[0])); 1422 else 1423 *port = '\0'; 1424 ret += websWrite(wp, "<td><input name=\"filter_client_to_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1425 i, port); 1426 ret += websWrite(wp, "<td>-</td>"); 1427 if (valid) 1428 snprintf(port, sizeof(port), "%d", ntohs(start.match.dst.ports[1])); 1429 else 1430 *port = '\0'; 1431 ret += websWrite(wp, "<td><input name=\"filter_client_to_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1432 i, port); 1433 ret += websWrite(wp, "<td></td>"); 1434 1435 /* Print day range */ 1436 ret += websWrite(wp, "<td>"); 1437 ret += websWrite(wp, "<select name=\"filter_client_from_day%d\">", i); 1438 for (j = 0; j < ARRAYSIZE(days); j++) 1439 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", 1440 j, valid && start.match.days[0] == j ? "selected" : "", days[j]); 1441 ret += websWrite(wp, "</select>"); 1442 ret += websWrite(wp, "</td>"); 1443 ret += websWrite(wp, "<td>-</td>"); 1444 ret += websWrite(wp, "<td>"); 1445 ret += websWrite(wp, "<select name=\"filter_client_to_day%d\">", i); 1446 for (j = 0; j < ARRAYSIZE(days); j++) 1447 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", 1448 j, valid && start.match.days[1] == j ? "selected" : "", days[j]); 1449 ret += websWrite(wp, "</select>"); 1450 ret += websWrite(wp, "</td>"); 1451 ret += websWrite(wp, "<td></td>"); 1452 1453 /* Print time range */ 1454 ret += websWrite(wp, "<td>"); 1455 ret += websWrite(wp, "<select name=\"filter_client_from_sec%d\">", i); 1456 for (j = 0; j < ARRAYSIZE(hours); j++) 1457 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", 1458 j * 3600, valid && start.match.secs[0] == (j * 3600) ? "selected" : "", hours[j]); 1459 ret += websWrite(wp, "</select>"); 1460 ret += websWrite(wp, "</td>"); 1461 ret += websWrite(wp, "<td>-</td>"); 1462 1463 ret += websWrite(wp, "<td>"); 1464 ret += websWrite(wp, "<select name=\"filter_client_to_sec%d\">", i); 1465 for (j = 0; j < ARRAYSIZE(hours); j++) 1466 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", 1467 j * 3600, valid && start.match.secs[1] == (j * 3600) ? "selected" : "", hours[j]); 1468 /* Special case for 11:59:59 PM */ 1469 ret += websWrite(wp, "<option value=\"%d\" %s>12:00 AM</option>", 1470 24 * 3600 - 1, valid && start.match.secs[1] == (24 * 3600 - 1) ? "selected" : ""); 1471 ret += websWrite(wp, "</select>"); 1472 ret += websWrite(wp, "</td>"); 1473 ret += websWrite(wp, "<td></td>"); 1474 1475 /* Print enable */ 1476 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"filter_client_enable%d\" %s></td>", 1477 i, valid && !(start.match.flags & NETCONF_DISABLED) ? "checked" : ""); 1478 1479 ret += websWrite(wp, "</tr>"); 1480 } 1481 1482 return ret; 1483} 1484 1485/* 1486 * Example: 1487 * <% forward_port(1, 10); %> produces a table of the first 10 port forward entries 1488 */ 1489static int 1490ej_forward_port(int eid, webs_t wp, int argc, char_t **argv) 1491{ 1492 int i, n, ret = 0; 1493 netconf_nat_t nat; 1494 bool valid; 1495 char port[] = "XXXXX"; 1496 1497 if (ejArgs(argc, argv, "%d %d", &i, &n) < 2) { 1498 websError(wp, 400, "Insufficient args\n"); 1499 return -1; 1500 } 1501 1502 for (; i <= n; i++) { 1503 valid = get_forward_port(i, &nat); 1504 1505 ret += websWrite(wp, "<tr>"); 1506 ret += websWrite(wp, "<td></td>"); 1507 1508 /* Print protocol */ 1509 ret += websWrite(wp, "<td>"); 1510 ret += websWrite(wp, "<select name=\"forward_port_proto%d\">", i); 1511 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 1512 valid && nat.match.ipproto == IPPROTO_TCP ? "selected" : ""); 1513 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 1514 valid && nat.match.ipproto == IPPROTO_UDP ? "selected" : ""); 1515 ret += websWrite(wp, "</select>"); 1516 ret += websWrite(wp, "</td>"); 1517 ret += websWrite(wp, "<td></td>"); 1518 1519 /* Print WAN destination port range */ 1520 if (valid) 1521 snprintf(port, sizeof(port), "%d", ntohs(nat.match.dst.ports[0])); 1522 else 1523 *port = '\0'; 1524 ret += websWrite(wp, "<td><input name=\"forward_port_from_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1525 i, port); 1526 ret += websWrite(wp, "<td>-</td>"); 1527 if (valid) 1528 snprintf(port, sizeof(port), "%d", ntohs(nat.match.dst.ports[1])); 1529 else 1530 *port = '\0'; 1531 ret += websWrite(wp, "<td><input name=\"forward_port_from_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1532 i, port); 1533 ret += websWrite(wp, "<td>></td>"); 1534 1535 /* Print address range */ 1536 ret += websWrite(wp, "<td><input name=\"forward_port_to_ip%d\" value=\"%s\" size=\"15\" maxlength=\"15\"></td>", 1537 i, valid ? inet_ntoa(nat.ipaddr) : ""); 1538 ret += websWrite(wp, "<td>:</td>"); 1539 1540 /* Print LAN destination port range */ 1541 if (valid) 1542 snprintf(port, sizeof(port), "%d", ntohs(nat.ports[0])); 1543 else 1544 *port = '\0'; 1545 ret += websWrite(wp, "<td><input name=\"forward_port_to_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1546 i, port); 1547 ret += websWrite(wp, "<td>-</td>"); 1548 if (valid) 1549 snprintf(port, sizeof(port), "%d", ntohs(nat.ports[1])); 1550 else 1551 *port = '\0'; 1552 ret += websWrite(wp, "<td><input name=\"forward_port_to_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1553 i, port); 1554 ret += websWrite(wp, "<td></td>"); 1555 1556 /* Print enable */ 1557 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"forward_port_enable%d\" %s></td>", 1558 i, valid && !(nat.match.flags & NETCONF_DISABLED) ? "checked" : ""); 1559 1560 ret += websWrite(wp, "</tr>"); 1561 } 1562 1563 return ret; 1564} 1565 1566static int 1567ej_autofw_port(int eid, webs_t wp, int argc, char_t **argv) 1568{ 1569 int i, n, ret = 0; 1570 netconf_app_t app; 1571 bool valid; 1572 char port[] = "XXXXX"; 1573 1574 if (ejArgs(argc, argv, "%d %d", &i, &n) < 2) { 1575 websError(wp, 400, "Insufficient args\n"); 1576 return -1; 1577 } 1578 1579 for (; i <= n; i++) { 1580 valid = get_autofw_port(i, &app); 1581 1582 /* Parse out_proto:out_port,in_proto:in_start-in_end>to_start-to_end,enable,desc */ 1583 ret += websWrite(wp, "<tr>"); 1584 ret += websWrite(wp, "<td></td>"); 1585 1586 /* Print outbound protocol */ 1587 ret += websWrite(wp, "<td>"); 1588 ret += websWrite(wp, "<select name=\"autofw_port_out_proto%d\">", i); 1589 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 1590 valid && app.match.ipproto == IPPROTO_TCP ? "selected" : ""); 1591 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 1592 valid && app.match.ipproto == IPPROTO_UDP ? "selected" : ""); 1593 ret += websWrite(wp, "</select>"); 1594 ret += websWrite(wp, "</td>"); 1595 ret += websWrite(wp, "<td></td>"); 1596 1597 /* Print outbound port */ 1598 if (valid) 1599 snprintf(port, sizeof(port), "%d", ntohs(app.match.dst.ports[0])); 1600 else 1601 *port = '\0'; 1602 ret += websWrite(wp, "<td><input name=\"autofw_port_out_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1603 i, port); 1604 ret += websWrite(wp, "<td>-</td>"); 1605 if (valid) 1606 snprintf(port, sizeof(port), "%d", ntohs(app.match.dst.ports[1])); 1607 else 1608 *port = '\0'; 1609 ret += websWrite(wp, "<td><input name=\"autofw_port_out_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1610 i, port); 1611 ret += websWrite(wp, "<td></td>"); 1612 1613 /* Print related protocol */ 1614 ret += websWrite(wp, "<td>"); 1615 ret += websWrite(wp, "<select name=\"autofw_port_in_proto%d\">", i); 1616 ret += websWrite(wp, "<option value=\"tcp\" %s>TCP</option>", 1617 valid && app.proto == IPPROTO_TCP ? "selected" : ""); 1618 ret += websWrite(wp, "<option value=\"udp\" %s>UDP</option>", 1619 valid && app.proto == IPPROTO_UDP ? "selected" : ""); 1620 ret += websWrite(wp, "</select>"); 1621 ret += websWrite(wp, "</td>"); 1622 ret += websWrite(wp, "<td></td>"); 1623 1624 /* Print related destination port range */ 1625 if (valid) 1626 snprintf(port, sizeof(port), "%d", ntohs(app.dport[0])); 1627 else 1628 *port = '\0'; 1629 ret += websWrite(wp, "<td><input name=\"autofw_port_in_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1630 i, port); 1631 ret += websWrite(wp, "<td>-</td>"); 1632 if (valid) 1633 snprintf(port, sizeof(port), "%d", ntohs(app.dport[1])); 1634 else 1635 *port = '\0'; 1636 ret += websWrite(wp, "<td><input name=\"autofw_port_in_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1637 i, port); 1638 ret += websWrite(wp, "<td></td>"); 1639 1640 /* Print mapped destination port range */ 1641 if (valid) 1642 snprintf(port, sizeof(port), "%d", ntohs(app.to[0])); 1643 else 1644 *port = '\0'; 1645 ret += websWrite(wp, "<td><input name=\"autofw_port_to_start%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1646 i, port); 1647 ret += websWrite(wp, "<td>-</td>"); 1648 if (valid) 1649 snprintf(port, sizeof(port), "%d", ntohs(app.to[1])); 1650 else 1651 *port = '\0'; 1652 ret += websWrite(wp, "<td><input name=\"autofw_port_to_end%d\" value=\"%s\" size=\"5\" maxlength=\"5\"></td>", 1653 i, port); 1654 ret += websWrite(wp, "<td></td>"); 1655 1656 /* Print enable */ 1657 ret += websWrite(wp, "<td><input type=\"checkbox\" name=\"autofw_port_enable%d\" %s></td>", 1658 i, valid && !(app.match.flags & NETCONF_DISABLED) ? "checked" : ""); 1659 1660 ret += websWrite(wp, "</tr>"); 1661 } 1662 1663 return ret; 1664} 1665#endif /* __CONFIG_NAT__ */ 1666 1667/* 1668 * Example: 1669 * lan_route=192.168.2.0:255.255.255.0:192.168.2.1:1 1670 * <% lan_route("ipaddr", 0); %> produces "192.168.2.0" 1671 */ 1672static int 1673ej_lan_route(int eid, webs_t wp, int argc, char_t **argv) 1674{ 1675 char *arg; 1676 int which; 1677 char word[256], *next; 1678 char *ipaddr, *netmask, *gateway, *metric; 1679 1680 if (ejArgs(argc, argv, "%s %d", &arg, &which) < 2) { 1681 websError(wp, 400, "Insufficient args\n"); 1682 return -1; 1683 } 1684 1685 foreach(word, nvram_safe_get("lan_route"), next) { 1686 if (which-- == 0) { 1687 netmask = word; 1688 ipaddr = strsep(&netmask, ":"); 1689 if (!ipaddr || !netmask) 1690 continue; 1691 gateway = netmask; 1692 netmask = strsep(&gateway, ":"); 1693 if (!netmask || !gateway) 1694 continue; 1695 metric = gateway; 1696 gateway = strsep(&metric, ":"); 1697 if (!gateway || !metric) 1698 continue; 1699 if (!strcmp(arg, "ipaddr")) 1700 return websWrite(wp, ipaddr); 1701 else if (!strcmp(arg, "netmask")) 1702 return websWrite(wp, netmask); 1703 else if (!strcmp(arg, "gateway")) 1704 return websWrite(wp, gateway); 1705 else if (!strcmp(arg, "metric")) 1706 return websWrite(wp, metric); 1707 } 1708 } 1709 1710 return 0; 1711} 1712 1713#ifdef __CONFIG_NAT__ 1714/* 1715 * Example: 1716 * wan_route=192.168.10.0:255.255.255.0:192.168.10.1:1 1717 * <% wan_route("ipaddr", 0); %> produces "192.168.10.0" 1718 */ 1719static int 1720ej_wan_route(int eid, webs_t wp, int argc, char_t **argv) 1721{ 1722 char *arg; 1723 int which; 1724 char word[256], *next; 1725 char *ipaddr, *netmask, *gateway, *metric; 1726 int unit; 1727 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 1728 1729 1730 if (ejArgs(argc, argv, "%s %d", &arg, &which) < 2) {websError(wp, 400, "Insufficient args\n"); 1731 websError(wp, 400, "Insufficient args\n"); 1732 return -1; 1733 } 1734 1735 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 1736 unit = 0; 1737 wan_prefix(unit, prefix); 1738 1739 foreach(word, nvram_safe_get(strcat_r(prefix, "route", tmp)), next) { 1740 if (which-- == 0) { 1741 netmask = word; 1742 ipaddr = strsep(&netmask, ":"); 1743 if (!ipaddr || !netmask) 1744 continue; 1745 gateway = netmask; 1746 netmask = strsep(&gateway, ":"); 1747 if (!netmask || !gateway) 1748 continue; 1749 metric = gateway; 1750 gateway = strsep(&metric, ":"); 1751 if (!gateway || !metric) 1752 continue; 1753 if (!strcmp(arg, "ipaddr")) 1754 return websWrite(wp, ipaddr); 1755 else if (!strcmp(arg, "netmask")) 1756 return websWrite(wp, netmask); 1757 else if (!strcmp(arg, "gateway")) 1758 return websWrite(wp, gateway); 1759 else if (!strcmp(arg, "metric")) 1760 return websWrite(wp, metric); 1761 } 1762 } 1763 1764 return 0; 1765} 1766#endif /* __CONFIG_NAT__ */ 1767 1768/* Return a list of the currently present wireless interfaces */ 1769static int 1770ej_wl_list(int eid, webs_t wp, int argc, char_t **argv) 1771{ 1772 char name[IFNAMSIZ], *next=NULL; 1773 char wl_name[IFNAMSIZ],os_name[IFNAMSIZ]; 1774 int unit=-1,subunit=-1, ret = 0; 1775 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1776 char unit_str[]="000000"; 1777 char *hwaddr=NULL, *ssid=NULL, *virtual=NULL; 1778 char ifnames[256]; 1779 1780 if (ejArgs(argc, argv, "%s", &virtual) > 0) { 1781 if (strcmp(virtual,"INCLUDE_VIFS")){ 1782 websError(wp, 400, "Unknown argument %s\n",virtual); 1783 return -1; 1784 } 1785 } 1786 1787 1788 snprintf(ifnames, sizeof(ifnames), "%s %s %s", 1789 nvram_safe_get("wan_ifnames"), 1790 nvram_safe_get("lan_ifnames"), 1791 nvram_safe_get("unbridged_ifnames")); 1792 1793 if (!remove_dups(ifnames,sizeof(ifnames))){ 1794 websError(wp, 400, "Unable to remove duplicate interfaces from ifname list<br>"); 1795 return -1; 1796 } 1797 1798 foreach(name, ifnames, next) { 1799 1800 if ( nvifname_to_osifname( name, os_name, sizeof(os_name) ) < 0 ) 1801 continue; 1802 1803 if (wl_probe(os_name) || 1804 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit))) 1805 continue; 1806 1807 /* Convert eth name to wl name */ 1808 1809 if( osifname_to_nvifname( name, wl_name, sizeof(wl_name) ) != 0 ) 1810 { 1811 websError(wp, 400, "wl name for interface:%s not found\n",name); 1812 return -1; 1813 } 1814 1815 /* Get configured ethernet MAC address */ 1816 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 1817 hwaddr = nvram_get(strcat_r(prefix, "hwaddr", tmp)); 1818 1819 /* Slave intefaces have a '.' in the name. assume the MAC address 1820 is the same as the primary interface*/ 1821 if (strchr(wl_name,'.')) { 1822 /* If Physical interfaces are specified do not 1823 process the slave interfaces skip writing out the info 1824 */ 1825 if (virtual) 1826 snprintf(prefix, sizeof(prefix),"%s_",wl_name); 1827 else 1828 continue; 1829 } 1830 1831 if (get_ifname_unit(wl_name,&unit,&subunit) < 0) { 1832 websError(wp, 400, "Error extracting unit and subunit name from %s\n",wl_name); 1833 return -1; 1834 } 1835 1836 /* Should not need to test if pysical interfaces flag is set, 1837 since that the code above will skip this portion. However 1838 it guards against future problems if this gets reworked 1839 in the future as the explicit checks here prevent any 1840 ambiguity 1841 */ 1842 1843 if ((subunit > 0 ) && (virtual) ) 1844 snprintf(unit_str,sizeof(unit_str),"%d.%d",unit,subunit); 1845 else 1846 snprintf(unit_str,sizeof(unit_str),"%d",unit); 1847 1848 ssid = nvram_get(strcat_r(prefix, "ssid", tmp)); 1849 1850 if (!hwaddr || !*hwaddr || !ssid || !*ssid) 1851 continue; 1852 1853 ret += websWrite(wp, "<option value=\"%s\" %s>%s(%s)</option>\n", unit_str, 1854 (!strncmp(unit_str,nvram_safe_get("wl_unit"),sizeof(unit_str))) ? "selected" : "", 1855 ssid, hwaddr); 1856 } 1857 1858 if (!ret) 1859 ret += websWrite(wp, "<option value=\"-1\" selected>None</option>"); 1860 1861 return ret; 1862} 1863 1864/* Return a list of the supported bands on the currently selected wireless interface */ 1865static int 1866ej_wl_phytypes(int eid, webs_t wp, int argc, char_t **argv) 1867{ 1868 int ret = 0; 1869 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1870 char *phytype=NULL; 1871 char *phylist=NULL; 1872 int i=0; 1873 1874 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) 1875 return websWrite(wp, "None"); 1876 1877 /* Get available phy types of the currently selected wireless interface */ 1878 phylist = nvram_safe_get(strcat_r(prefix, "phytypes", tmp)); 1879 1880 /* Get configured phy type */ 1881 phytype = nvram_safe_get("wl_phytype"); 1882 1883 for (i = 0; i < strlen(phylist); i++) { 1884 ret += websWrite(wp, "<option value=\"%c\" %s>802.11%c (%s GHz)</option>", 1885 phylist[i], phylist[i] == *phytype ? "selected" : "", phylist[i], 1886 phylist[i] == 'a' ? "5" : "2.4"); 1887 } 1888 1889 return ret; 1890} 1891 1892/* Return a radio ID given a phy type */ 1893static int 1894ej_wl_radioid(int eid, webs_t wp, int argc, char_t **argv) 1895{ 1896 char *phytype=NULL, var[NVRAM_BUFSIZE], *next; 1897 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1898 int which; 1899 1900 if (ejArgs(argc, argv, "%s", &phytype) < 1) { 1901 websError(wp, 400, "Insufficient args\n"); 1902 return -1; 1903 } 1904 1905 assert(phytype); 1906 1907 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) 1908 return websWrite(wp, "None"); 1909 1910 which = strcspn(nvram_safe_get(strcat_r(prefix, "phytypes", tmp)), phytype); 1911 foreach(var, nvram_safe_get(strcat_r(prefix, "radioids", tmp)), next) { 1912 if (which == 0) 1913 return websWrite(wp, var); 1914 which--; 1915 } 1916 1917 return websWrite(wp, "None"); 1918} 1919 1920/* Return current core revision */ 1921static int 1922ej_wl_corerev(int eid, webs_t wp, int argc, char_t **argv) 1923{ 1924 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1925 1926 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)) 1927 return websWrite(wp, "None"); 1928 1929 return websWrite(wp, nvram_safe_get(strcat_r(prefix, "corerev", tmp))); 1930} 1931 1932/* Return current wireless channel */ 1933static int 1934ej_wl_cur_channel(int eid, webs_t wp, int argc, char_t **argv) 1935{ 1936 char *name=NULL; 1937 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1938 channel_info_t ci; 1939 1940 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 1941 websError(wp, 400, "unit number variable doesn't exist\n"); 1942 return -1; 1943 } 1944 1945 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1946 1947 wl_ioctl(name, WLC_GET_CHANNEL, &ci, sizeof(ci)); 1948 return websWrite(wp, "Current: %d", ci.target_channel); 1949} 1950 1951/* Return current country */ 1952static int 1953ej_wl_cur_country(int eid, webs_t wp, int argc, char_t **argv) 1954{ 1955 char *name=NULL; 1956 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1957 char buf[WLC_CNTRY_BUF_SZ]; 1958 1959 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 1960 websError(wp, 400, "unit number variable doesn't exist\n"); 1961 return -1; 1962 } 1963 1964 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1965 1966 wl_ioctl(name, WLC_GET_COUNTRY, buf, sizeof(buf)); 1967 return websWrite(wp, "%s", buf); 1968} 1969 1970/* Return current phytype */ 1971static int 1972ej_wl_cur_phytype(int eid, webs_t wp, int argc, char_t **argv) 1973{ 1974 char *name; 1975 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 1976 int phytype; 1977 1978 if (!make_wl_prefix(prefix,sizeof(prefix),0,NULL)){ 1979 websError(wp, 400, "unit number variable doesn't exist\n"); 1980 return -1; 1981 } 1982 1983 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1984 1985 /* Get configured phy type */ 1986 wl_ioctl(name, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)); 1987 1988 return websWrite(wp, "Current: 802.11%s", phytype == WLC_PHY_TYPE_A ? "a" : 1989 phytype == WLC_PHY_TYPE_B ? "b" : "g"); 1990} 1991 1992#ifdef __CONFIG_NAT__ 1993static char * 1994wan_name(int unit, char *prefix, char *name, int len) 1995{ 1996 char tmp[NVRAM_BUFSIZE], *desc; 1997 desc = nvram_safe_get(strcat_r(prefix, "desc", tmp)); 1998 snprintf(tmp, sizeof(tmp), "Connection %d", unit + 1); 1999 snprintf(name, len, "%s", !strcmp(desc, "") ? tmp : desc); 2000 return name; 2001} 2002 2003/* Return a list of wan connections (Connection <N>/<Connection Name>) */ 2004static int 2005ej_wan_list(int eid, webs_t wp, int argc, char_t **argv) 2006{ 2007 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 2008 int unit, ret = 0; 2009 2010 /* build wan connection name list */ 2011 for (unit = 0; unit < MAX_NVPARSE; unit ++) { 2012 wan_prefix(unit, prefix); 2013 if (!nvram_get(strcat_r(prefix, "unit", tmp))) 2014 continue; 2015 ret += websWrite(wp, "<option value=\"%d\" %s>%s</option>", unit, 2016 unit == atoi(nvram_safe_get("wan_unit")) ? "selected" : "", 2017 wan_name(unit, prefix, tmp, sizeof(tmp))); 2018 } 2019 2020 return ret; 2021} 2022#endif /* __CONFIG_NAT__ */ 2023 2024/* write "selected" to page if the argument matches the current 2025 wl_ure setting */ 2026static int 2027ej_ure_list(int eid, webs_t wp, int argc, char_t **argv) 2028{ 2029 char *temp; 2030 int match_value; 2031 int nv_value; 2032 2033 if (ejArgs(argc, argv, "%d", &match_value) < 1) { 2034 websError(wp, 400, "Insufficient args\n"); 2035 return EINVAL; 2036 } 2037 2038 temp = nvram_get("wl_ure"); 2039 if(strlen( temp ) == 0) { 2040 if( match_value == 0 ) 2041 { 2042 /* treat empty string as "0" */ 2043 websWrite(wp, "selected" ); 2044 } 2045 return 0; 2046 } 2047 2048 nv_value = atoi( temp ); 2049 if( nv_value == match_value) { 2050 websWrite(wp, "selected" ); 2051 } 2052 2053 return 0; 2054} 2055 2056/* Return wlX_ure setting for the current wireless interface. If 2057 the current wireless interface is a virtual interface, return 2058 the value of the parent interface 2059*/ 2060static int 2061ej_ure_enabled(int eid, webs_t wp, int argc, char_t **argv) 2062{ 2063 char *temp; 2064 int unit = -1; 2065 int sub_unit = -1; 2066 char nv_param[NVRAM_MAX_PARAM_LEN]; 2067 2068 temp = nvram_get("wl_unit"); 2069 if(strlen( temp ) == 0) { 2070 websError(wp, 400, "Error getting wl_unit\n"); 2071 return EINVAL; 2072 } 2073 2074 if( get_ifname_unit( temp, &unit, &sub_unit ) != 0 ) { 2075 websError(wp, 400, "Error getting unit/subunit\n"); 2076 return EINVAL; 2077 } 2078 2079 sprintf( nv_param, "wl%d_ure", unit ); 2080 temp = nvram_safe_get( nv_param ); 2081 if( strncmp( temp, "1", 1 ) == 0 ) { 2082 websWrite(wp, "\"1\""); 2083 } 2084 else { 2085 websWrite(wp, "\"0\""); 2086 } 2087 2088 return 0; 2089} 2090 2091 2092char *webs_buf=NULL; 2093int webs_buf_offset=0; 2094 2095/* This routine extracts the index variable in the string 2096 format 2097 eg get_string_index("lan_","lan0_ifname",buf,sizeof(buf)) 2098 returns the string "0" in buf. 2099 2100 In the case of where there is no index 2101 eg get_string_index("lan_","lan_ifname",buf,sizeof(buf)) 2102 returns NULL in buf[0]. 2103 2104 Inputs : 2105 - prefix: prefix to start of index string 2106 - varname: value to process 2107 - outbuf: output buffer 2108 - bufsize: output buffer size 2109 2110 Returns: 2111 -string null terminated string in output buffer 2112 -pointer to output buffer or NULL if error 2113*/ 2114char * 2115get_index_string(char *prefix, char *varname, char *outbuf, int bufsize) 2116{ 2117 int offset, len; 2118 2119 if (!prefix) return NULL; 2120 if (!varname) return NULL; 2121 if (!outbuf) return NULL; 2122 if (!bufsize) return NULL; 2123 2124 memset(outbuf,0,bufsize); 2125 2126 /* offset is the start of the index number eg 2127 * offset of dhcp0 is 4. prefix contains the "dhcp" as 2128 * the prefix 2129 */ 2130 2131 offset = strlen(prefix); 2132 2133 /* This calculates the string length of the index 2134 * ie the index value represented as a string 2135 * strchr(varname,'_') is the end of the index string. 2136 * strchr(varname,'_') - varname is the length of the var including 2137 * the index string but before the underscore "_" 2138 */ 2139 len = strchr(varname,'_') - varname - offset ; 2140 2141 if (len > bufsize) return NULL; 2142 2143 if (len) strncpy(outbuf,&varname[offset],len); 2144 outbuf[len]='\0'; 2145 2146 return outbuf; 2147} 2148 2149static void 2150validate_list(webs_t wp, char *value, struct variable *v, 2151 int (*valid)(webs_t, char *, struct variable *), char *varname ) 2152{ 2153 int n, i; 2154 char name[100]; 2155 char buf[1000] = "", *cur = buf; 2156 2157 assert(v); 2158 2159 ret_code = EINVAL; 2160 n = atoi(value); 2161 2162 for (i = 0; i < n; i++) { 2163 snprintf(name, sizeof(name), "%s%d", v->name, i); 2164 if (!(value = websGetVar(wp, name, NULL))) 2165 return; 2166 2167 if (!*value && v->nullok) 2168 continue; 2169 if (!valid(wp, value, v )) 2170 continue; 2171 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s", 2172 cur == buf ? "" : " ", value); 2173 } 2174 2175 /* Use varname override if specified. Used to make the routine 2176 multiinstance compatible */ 2177 if (varname) 2178 nvram_set(varname, buf); 2179 else 2180 nvram_set(v->name, buf); 2181 2182 ret_code = 0; 2183} 2184 2185static int 2186valid_ipaddr(webs_t wp, char *value, struct variable *v) 2187{ 2188 unsigned int buf[4]; 2189 struct in_addr ipaddr, netaddr, broadaddr, netmask; 2190 2191 assert(v); 2192 2193 if (sscanf(value, "%d.%d.%d.%d", &buf[0], &buf[1], &buf[2], &buf[3]) != 4) { 2194 websBufferWrite(wp, "Invalid <b>%s</b> %s: not an IP address<br>", 2195 v->longname, value); 2196 return FALSE; 2197 } 2198 2199 ipaddr.s_addr = htonl((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); 2200 2201 if (v->argv) { 2202 (void) inet_aton(nvram_safe_get(v->argv[0]), &netaddr); 2203 (void) inet_aton(nvram_safe_get(v->argv[1]), &netmask); 2204 netaddr.s_addr &= netmask.s_addr; 2205 broadaddr.s_addr = netaddr.s_addr | ~netmask.s_addr; 2206 if (netaddr.s_addr != (ipaddr.s_addr & netmask.s_addr)) { 2207 websBufferWrite(wp, "Invalid <b>%s</b> %s: not in the %s/", 2208 v->longname, value, inet_ntoa(netaddr)); 2209 websBufferWrite(wp, "%s network<br>", inet_ntoa(netmask)); 2210 return FALSE; 2211 } 2212 if (ipaddr.s_addr == netaddr.s_addr) { 2213 websBufferWrite(wp, "Invalid <b>%s</b> %s: cannot be the network address<br>", 2214 v->longname, value); 2215 return FALSE; 2216 } 2217 if (ipaddr.s_addr == broadaddr.s_addr) { 2218 websBufferWrite(wp, "Invalid <b>%s</b> %s: cannot be the broadcast address<br>", 2219 v->longname, value); 2220 return FALSE; 2221 } 2222 } 2223 2224 return TRUE; 2225} 2226 2227static void 2228validate_ipaddr(webs_t wp, char *value, struct variable *v , char *varname) 2229{ 2230 2231 assert(v); 2232 2233 ret_code = EINVAL; 2234 2235 if (!valid_ipaddr(wp, value, v) ) return; 2236 2237 if (varname) 2238 nvram_set(varname,value) ; 2239 else 2240 nvram_set(v->name, value); 2241 2242 ret_code = 0; 2243 2244} 2245 2246static void 2247validate_ipaddrs(webs_t wp, char *value, struct variable *v, char *varname) 2248{ 2249 ret_code = EINVAL; 2250 validate_list(wp, value, v, valid_ipaddr, varname); 2251} 2252 2253static int 2254valid_choice(webs_t wp, char *value, struct variable *v) 2255{ 2256 char **choice=NULL; 2257 2258 assert(v); 2259 2260 for (choice = v->argv; *choice; choice++) { 2261 if (!strcmp(value, *choice)) 2262 return TRUE; 2263 } 2264 2265 websBufferWrite(wp, "Invalid <b>%s</b> %s: not one of ", v->longname, value); 2266 for (choice = v->argv; *choice; choice++) 2267 websBufferWrite(wp, "%s%s", choice == v->argv ? "" : "/", *choice); 2268 websBufferWrite(wp, "<br>"); 2269 2270 return FALSE; 2271} 2272 2273static void 2274validate_choice(webs_t wp, char *value, struct variable *v, char *varname) 2275{ 2276 2277 assert(v); 2278 2279 ret_code = EINVAL; 2280 2281 if (!valid_choice(wp, value, v)) return; 2282 2283 if (varname ) 2284 nvram_set(varname,value) ; 2285 else 2286 nvram_set(v->name, value); 2287 ret_code = 0; 2288 2289} 2290 2291static void 2292validate_router_disable(webs_t wp, char *value, struct variable *v, 2293 char *varname) 2294{ 2295 char *temp = NULL; 2296 2297 assert(v); 2298 2299 ret_code = EINVAL; 2300 2301 if (!valid_choice(wp, value, v)) return; 2302 2303 /* we need to find out if we're changing the router mode or not. if 2304 we're really changing the setting, we need to reboot */ 2305 temp = nvram_safe_get( v->name ); 2306 2307 cprintf( "\n\n temp = %s, value = %s\n\n", temp, value ); 2308 2309 if( strcmp( temp, value ) ) 2310 action = REBOOT; 2311 2312 if (varname ) 2313 nvram_set(varname,value) ; 2314 else 2315 nvram_set(v->name, value); 2316 ret_code = 0; 2317 2318} 2319 2320static int 2321valid_range(webs_t wp, char *value, struct variable *v) 2322{ 2323 int n, start, end; 2324 2325 assert(v); 2326 2327 n = atoi(value); 2328 start = atoi(v->argv[0]); 2329 end = atoi(v->argv[1]); 2330 2331 if (n < start || n > end) { 2332 websBufferWrite(wp, "Invalid <b>%s</b> %s: out of range %d-%d<br>", 2333 v->longname, value, start, end); 2334 return FALSE; 2335 } 2336 2337 return TRUE; 2338} 2339 2340static void 2341validate_range(webs_t wp, char *value, struct variable *v , char *varname) 2342{ 2343 2344 assert(v); 2345 2346 ret_code = EINVAL; 2347 2348 if (!valid_range(wp, value, v)) return ; 2349 2350 if (varname ) 2351 nvram_set(varname,value) ; 2352 else 2353 nvram_set(v->name, value); 2354 2355 ret_code = 0; 2356} 2357 2358static int 2359valid_name(webs_t wp, char *value, struct variable *v) 2360{ 2361 int n, min, max; 2362 2363 assert(v); 2364 2365 n = strlen(value); 2366 min = atoi(v->argv[0]); 2367 max = atoi(v->argv[1]); 2368 2369 if (n > max) { 2370 websBufferWrite(wp, "Invalid <b>%s</b> %s: longer than %d characters<br>", 2371 v->longname, value, max); 2372 return FALSE; 2373 } 2374 else if (n < min) { 2375 websBufferWrite(wp, "Invalid <b>%s</b> %s: shorter than %d characters<br>", 2376 v->longname, value, min); 2377 return FALSE; 2378 } 2379 2380 return TRUE; 2381} 2382 2383static void 2384validate_guest_lan_ifname(webs_t wp, char *value, struct variable *v, char *varname ) 2385{ 2386 int index,unit; 2387 char ifname[IFNAMSIZ],os_name[IFNAMSIZ]; 2388 2389 assert(v); 2390 assert(value); 2391 2392 ret_code = EINVAL; 2393 2394 if (!*value){ 2395 websBufferWrite(wp, "Guest LAN interface must be specified.<br>"); 2396 return; 2397 } 2398 2399 if (!v->argv[0]){ 2400 websBufferWrite(wp, "Guest LAN interface index must be specified.<br>"); 2401 return; 2402 } 2403 2404 index = atoi (v->argv[0]); 2405 2406 if ((index < 1 ) || (index > 4)) 2407 if (!v->argv[0]){ 2408 websBufferWrite(wp, "Guest LAN interface index must be between 1 and 4.<br>"); 2409 return; 2410 } 2411 2412 if (nvifname_to_osifname( value, os_name, sizeof(os_name) ) < 0){ 2413 websBufferWrite(wp, "Unable to translate Guest LAN interface name: %s.<br>",value); 2414 return; 2415 } 2416 2417 if (wl_probe(os_name) || 2418 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit))){ 2419 websBufferWrite(wp, "Guest LAN interface %s is not a Wireless Interface.<br>",value); 2420 return; 2421 } 2422 2423 /* Guest SSID are not part of a bridge, unset lanX_ifnames */ 2424 2425 snprintf(ifname,sizeof(ifname),"lan%d_ifname",index); 2426 nvram_set(ifname,value); 2427 2428 snprintf(ifname,sizeof(ifname),"lan%d_ifnames",index); 2429 nvram_unset(ifname); 2430 2431 ret_code=0; 2432} 2433static void 2434validate_guest_ssid(webs_t wp, char *value, struct variable *v, char *varname ) 2435{ 2436/* Validation of the guest ssids does 3 things 2437 * 1)adds the wlX.Y_ssid field 2438 * 2)updates the wlX_vif list 2439 * 3)removes entry from wlX_vif if the interface is empty 2440*/ 2441 2442 char *wl_unit=NULL; 2443 char wl_vif[]="wlXXXXXXXXX_vifs",*wl_vif_value=NULL; 2444 char wl_ssid[]="wlXXXXXXXXX_ssid"; 2445 char wl_guest[]="wlXXXXXXXXX_guest"; 2446 char wl_radio[]="wlXXXXXXXXX_radio"; 2447 char wl_mode[]="wlXXXXXXXXX_mode"; 2448 char buf[]="wlXXXXXXXXX_vifs"; 2449 char prefix[]="wlXXXXX"; 2450 int p=-1; 2451 char *subunit=NULL,unit[]="0000"; 2452 char *argv[3]; 2453 int wl_ure = -1; 2454 2455 assert(v); 2456 assert(value); 2457 2458 ret_code = EINVAL; 2459 2460 2461 if (varname) 2462 wl_unit=varname; 2463 else 2464 2465 wl_unit=websGetVar(wp, "wl_unit", NULL); 2466 2467 if (get_ifname_unit(wl_unit,&p,NULL) < 0) return ; 2468 2469 if (p < 0) return; 2470 2471 snprintf(unit,sizeof(unit),"%d",p); 2472 subunit = v->argv[0]; 2473 2474 /* If SSID is not null try to validate it for correct range */ 2475 if (*value){ 2476 struct variable local; 2477 2478 memcpy(&local,v,sizeof(local)); 2479 argv[0]="1"; 2480 argv[1]="32"; 2481 argv[2]=NULL; 2482 local.argv=argv; 2483 if (!valid_name(wp, value, &local)) return; 2484 } 2485 2486 snprintf(wl_ssid,sizeof(wl_ssid),"wl%s.%s_ssid",unit,subunit); 2487 snprintf(wl_vif,sizeof(wl_vif),"wl%s_vifs",unit); 2488 snprintf(wl_guest,sizeof(wl_guest),"wl%s.%s_guest",unit,subunit); 2489 2490 memset(buf,0,sizeof(buf)); 2491 2492 /* This logic here decides if updates to virtual interface list on the 2493 parent is required */ 2494 2495 wl_vif_value = nvram_get(wl_vif); 2496 2497 if (wl_vif_value ){ 2498 char vif[]="wlXXXXXXXXX"; 2499 char *ptr=NULL; 2500 2501 snprintf(vif,sizeof(vif),"wl%s.%s",unit,subunit); 2502 2503 /* Look to see if the virtual interface is present on 2504 on the list already 2505 */ 2506 ptr=strstr(wl_vif_value,vif); 2507 2508 if (*value){ 2509 /* New interface , non-NULL SSID add to wl_vifs */ 2510 if (!ptr) 2511 snprintf(buf,sizeof(buf),"%s wl%s.%s",wl_vif_value,unit,subunit); 2512 else 2513 /* Interface present ,non-NULL SSID copy entire vifs string */ 2514 snprintf(buf,sizeof(buf),"%s",wl_vif_value); 2515 }else{ 2516 /* Purge interface from wl_vifs as the SSID is now NULL */ 2517 2518 /* vif present , delete from wl_vifs */ 2519 if ((ptr)){ 2520 char name[IFNAMSIZ], *next = NULL; 2521 2522 memset(buf,0,sizeof(buf)); 2523 2524 foreach(name,wl_vif_value,next) 2525 /* Copy all the interfaces except the the one we want to remove*/ 2526 if (strcmp(name,vif)){ 2527 int len; 2528 2529 len = strlen(buf); 2530 if (*buf) 2531 strncat(buf," ",len-1); 2532 strncat(buf,name,len-strlen(name)); 2533 } 2534 }else 2535 /* Interface absent from wl_vifs, just copy vifs string */ 2536 snprintf(buf,sizeof(buf),"%s",wl_vif_value); 2537 } 2538 }else 2539 if (*value) snprintf(buf,sizeof(buf),"wl%s.%s",unit,subunit); 2540 2541 /* before allowing any "nvram_set()": If URE is enabled, we want to 2542 error here if an SSID isn't present */ 2543 wl_ure = atoi( websGetVar( wp, "wl_ure", NULL ) ); 2544 if(( wl_ure == 1) && (strlen(value) == 0 )) 2545 { 2546 websError(wp, 400, "Guest SSID not defined for URE mode\n"); 2547 ret_code = EINVAL; 2548 return; 2549 } 2550 2551 /* Regenerate virtual interface list */ 2552 if (*buf) 2553 nvram_set(wl_vif,buf); 2554 else 2555 nvram_unset(wl_vif); 2556 2557 2558 /* Update/clean up wlX.Y_guest flag and wlX.Y_ssid */ 2559 2560 snprintf(prefix,sizeof(prefix),"wl%s.%s",unit,subunit); 2561 snprintf(wl_radio,sizeof(wl_radio),"wl%s.%s_radio",unit,subunit); 2562 snprintf(wl_mode,sizeof(wl_mode),"wl%s.%s_mode",unit,subunit); 2563 2564 if (*value){ 2565 if ( wl_ure == 0 ) 2566 nvram_set(wl_guest,"1"); 2567 else 2568 nvram_unset(wl_guest); 2569 nvram_set(wl_mode,"ap"); 2570 nvram_set(wl_ssid,value); 2571 nvram_set(wl_radio,"1"); 2572 }else{ 2573 nvram_unset(wl_ssid); 2574 nvram_set(wl_guest,"0"); 2575 nvram_unset(wl_radio); 2576 nvram_unset(wl_mode); 2577 } 2578 2579 ret_code = 0; 2580} 2581static void 2582validate_name(webs_t wp, char *value, struct variable *v, char *varname ) 2583{ 2584 ret_code = EINVAL; 2585 2586 assert(v); 2587 2588 if (!valid_name(wp, value, v)) return; 2589 2590 if (varname ) 2591 nvram_set(varname,value) ; 2592 else 2593 nvram_set(v->name, value); 2594 2595 ret_code = 0; 2596} 2597 2598static void 2599validate_ure(webs_t wp, char *value, struct variable *v, char *varname) 2600{ 2601 char *temp=NULL; 2602 int wl_unit = -1; 2603 int wl_subunit = -1; 2604 int wl_ure = -1; 2605 int ii = 0; 2606 char nv_param[NVRAM_MAX_PARAM_LEN]; 2607 char nv_interface[NVRAM_MAX_PARAM_LEN]; 2608 char os_interface[NVRAM_MAX_PARAM_LEN]; 2609 char interface_list[NVRAM_MAX_VALUE_LEN]; 2610 int interface_list_size = sizeof(interface_list); 2611 char *wan0_ifname = "wan0_ifname"; 2612 char *lan_ifnames = "lan_ifnames"; 2613 char *wan_ifnames = "wan_ifnames"; 2614 2615 if ((temp = websGetVar(wp, "wl_unit", NULL))) 2616 { 2617 if( *temp ) 2618 get_ifname_unit( temp, &wl_unit, &wl_subunit ); 2619 2620 if( wl_subunit != -1 ) 2621 { 2622 websError(wp, 400, "URE can't be enabled for a virtual I/F\n"); 2623 ret_code = EINVAL; 2624 return; 2625 } 2626 } 2627 2628 if((temp = websGetVar(wp, "wl_ure", NULL))) 2629 { 2630 if( *temp ) 2631 wl_ure = atoi( temp ); 2632 } 2633 2634 if( wl_ure < 0 || wl_unit < 0 ) 2635 { 2636 websError(wp, 400, "Insufficient args\n"); 2637 ret_code = EINVAL; 2638 return; 2639 } 2640 2641#if defined(linux) 2642 if ( nvram_match( "router_disable", "1" ) && wl_ure == 1 ) 2643 { 2644 websError(wp, 400, "Basic Page: Router Mode != Router\n"); 2645 ret_code = EINVAL; 2646 return; 2647 } 2648#endif /* defined( linux ) */ 2649 2650 if( wl_ure == 1 ) 2651 { 2652 /* turning on URE*/ 2653 2654 /* If TR, we can only allow a single TR interface */ 2655 for( ii = 0; ii < DEV_NUMIFS; ii++ ) { 2656 if( ii == wl_unit ) 2657 continue; 2658 2659 sprintf( nv_param, "wl%d_ure", ii ); 2660 temp = nvram_safe_get( nv_param ); 2661 if( temp && strlen( temp ) > 0 ) 2662 { 2663 if( atoi( temp ) == 1 ) { 2664 websError(wp, 400, "Can not have more than one URE interface\n"); 2665 ret_code = EINVAL; 2666 return; 2667 } 2668 } 2669 } 2670 2671 2672 /* Make sure that an SSID has been set for the virtual I/F here!!! */ 2673 temp = websGetVar(wp, "wl_guest_ssid_1", NULL); 2674 if ( !temp || strlen( temp ) == 0 ) 2675 { 2676 websError(wp, 400, "No definition for Guest SSID\n"); 2677 ret_code = EINVAL; 2678 return; 2679 } 2680 2681 sprintf( nv_param, "wl_ure" ); 2682 temp = nvram_safe_get( nv_param ); 2683 if( strncmp( temp, "0", 1 ) == 0 || strlen( temp ) == 0 ) 2684 { 2685 action = REBOOT; 2686 } 2687 else { 2688 /* nothing to do, bail out now */ 2689 return; 2690 } 2691 /* turn URE on for this primary interface */ 2692 nvram_set( nv_param, "1" ); 2693 2694 nvram_set( "ure_disable", "0" ); 2695 2696 /* Set the wl modes for the primary wireless adapter and it's 2697 virtual interface */ 2698 sprintf( nv_param, "wl%d_mode", wl_unit ); 2699 nvram_set( nv_param, "sta" ); 2700 nvram_set( "wl_mode", "sta" ); 2701 2702 sprintf( nv_param, "wl%d.1_mode", wl_unit ); 2703 nvram_set( nv_param, "ap" ); 2704 2705 /* For URE with routing(Travel Router)we're using the STA part of our URE 2706 enabled radio as our WAN connection. So, we need to remove this 2707 interface from the list of bridged lan interfaces and set it up as the 2708 WAN device. 2709 */ 2710 temp = nvram_safe_get(lan_ifnames); 2711 if( interface_list_size <= strlen( temp ) ) 2712 { 2713 websError(wp, 400, "string too long\n"); 2714 ret_code = 1; 2715 return; 2716 } 2717 strncpy( interface_list, temp, interface_list_size ); 2718 /* this may be confusing, right now the interface name that is stored 2719 in the nvram lists is OS specific. For linux it's an "ethX" for 2720 wireless interfaces and for VxWorks "wlX" is stored as "wlX" so 2721 this is trying to make OS independant code */ 2722 sprintf( nv_interface, "wl%d", wl_unit ); 2723 nvifname_to_osifname( nv_interface, os_interface, sizeof(os_interface) ); 2724 remove_from_list( os_interface, interface_list, interface_list_size ); 2725 nvram_set( lan_ifnames, interface_list ); 2726 2727 /* Now remove the existing WAN interface from "wan_ifnames" */ 2728 temp = nvram_safe_get( wan_ifnames ); 2729 if( interface_list_size <= (strlen( temp ) + strlen( interface_list )) ) 2730 { 2731 websError(wp, 400, "string too long\n"); 2732 ret_code = 1; 2733 return; 2734 } 2735 strncpy( interface_list, temp, interface_list_size ); 2736 temp = nvram_safe_get( wan0_ifname ); 2737 if( strlen( temp ) != 0 ) 2738 { 2739 remove_from_list( temp, interface_list, interface_list_size ); 2740 } 2741 2742 /* set the new WAN interface as the pimary WAN interface and add to 2743 the list wan_ifnames */ 2744 nvram_set( wan0_ifname, os_interface ); 2745 add_to_list( os_interface, interface_list, interface_list_size ); 2746 nvram_set( wan_ifnames, interface_list ); 2747 2748 /* now add the AP to the list of bridged lan interfaces */ 2749 temp = nvram_safe_get(lan_ifnames); 2750 if( interface_list_size <= strlen( temp ) ) 2751 { 2752 websError(wp, 400, "string too long\n"); 2753 ret_code = 1; 2754 return; 2755 } 2756 strncpy( interface_list, temp, interface_list_size ); 2757 sprintf( nv_interface, "wl%d.1", wl_unit ); 2758 /* virtual interfaces that appear in NVRAM lists are ALWAYS stored 2759 as the NVRAM_FORM so we can add to list without translating */ 2760 if( add_to_list( nv_interface, interface_list, interface_list_size ) != 0 ) 2761 { 2762 websError(wp, 400, "Failed to add AP interface to lan_ifnames\n"); 2763 ret_code = 1; 2764 return; 2765 } 2766 nvram_set( lan_ifnames, interface_list ); 2767 2768 /* Security - We don't support any RADIUS-based authentication, so 2769 we must force these options to OFF */ 2770 /* turn off wlX_auth_mode and wlX.1_auth_mode */ 2771 sprintf( nv_param, "wl%d_auth_mode", wl_unit ); 2772 nvram_set( nv_param, "none" ); 2773 sprintf( nv_param, "wl%d.1_auth_mode", wl_unit ); 2774 nvram_set( nv_param, "none" ); 2775 /* remove wpa and wpa2 from wlX_akm and wlX.1_akm */ 2776 /* wl_akm should be used here rather than wlX_akm, it's an 2777 indexed param, so wl_akm represents wlX_akm */ 2778 sprintf( nv_param, "wl_akm" ); 2779 temp = nvram_get( nv_param ); 2780 if( temp && *temp ) 2781 { 2782 memset( interface_list, 0, interface_list_size ); 2783 /* NOTE: using "interface_list" to hold security nvram values */ 2784 strncpy( interface_list, temp, interface_list_size - 1 ); 2785 remove_from_list("wpa", interface_list, interface_list_size ); 2786 remove_from_list("wpa2", interface_list, interface_list_size ); 2787 nvram_set( nv_param, interface_list ); 2788 } 2789 sprintf( nv_param, "wl%d.1_akm", wl_unit ); 2790 temp = nvram_get( nv_param ); 2791 if( temp && *temp ) 2792 { 2793 memset( interface_list, 0, interface_list_size ); 2794 /* NOTE: using "interface_list" to hold security nvram values */ 2795 strncpy( interface_list, temp, interface_list_size - 1 ); 2796 remove_from_list("wpa", interface_list, interface_list_size ); 2797 remove_from_list("wpa2", interface_list, interface_list_size ); 2798 nvram_set( nv_param, interface_list ); 2799 } 2800 } 2801 else 2802 { 2803 sprintf( nv_param, "wl_ure"); 2804 temp = nvram_get( nv_param ); 2805 if( strncmp( temp, "1", 1 ) != 0 ) { 2806 /* nothing to do, bail out now */ 2807 return; 2808 } 2809 nvram_set( nv_param, "0" ); 2810 2811 nvram_set( "ure_disable", "1" ); 2812 2813 /* Restore default WAN interface */ 2814 2815 /* Now remove the existing WAN interface from "wan_ifnames" */ 2816 temp = nvram_safe_get( wan_ifnames ); 2817 if( interface_list_size <= (strlen( temp ) + strlen( interface_list )) ) 2818 { 2819 websError(wp, 400, "string too long\n"); 2820 ret_code = 1; 2821 return; 2822 } 2823 strncpy( interface_list, temp, interface_list_size ); 2824 temp = nvram_safe_get( wan0_ifname ); 2825 if( strlen( temp ) != 0 ) 2826 { 2827 remove_from_list( temp, interface_list, interface_list_size ); 2828 } 2829 2830 strcpy( os_interface, "eth1" ); 2831 nvram_set( wan0_ifname, os_interface ); 2832 add_to_list( os_interface, interface_list, interface_list_size ); 2833 nvram_set( wan_ifnames, interface_list ); 2834 2835 /* Now we need to remove the virtual I/F from the bridged lan interfaces */ 2836 temp = nvram_safe_get(lan_ifnames); 2837 if( interface_list_size <= strlen( temp ) ) 2838 { 2839 websError(wp, 400, "string too long\n"); 2840 ret_code = 1; 2841 return; 2842 } 2843 strncpy( interface_list, temp, interface_list_size ); 2844 sprintf( nv_interface, "wl%d.1", wl_unit ); 2845 /* virtual interfaces that appear in NVRAM lists are ALWAYS stored 2846 as the NVRAM_FORM so we can add to list without translating */ 2847 remove_from_list( nv_interface, interface_list, interface_list_size ); 2848 /* Add our primary interface to lan_ifnames - default behavior */ 2849 sprintf( nv_interface, "wl%d", wl_unit ); 2850 nvifname_to_osifname( nv_interface, os_interface, sizeof(os_interface) ); 2851 add_to_list( os_interface, interface_list, interface_list_size ); 2852 nvram_set( lan_ifnames, interface_list ); 2853 } 2854 action = REBOOT; 2855 2856 /* We're unsetting the WAN hardware address so that we get the correct 2857 address for the new WAN interface the next time we boot. */ 2858 nvram_unset( "wan0_hwaddr" ); 2859 2860 ret_code = 0; 2861 return; 2862} 2863 2864static int 2865valid_hwaddr(webs_t wp, char *value, struct variable *v) 2866{ 2867 unsigned char hwaddr[6]; 2868 2869 assert(v); 2870 2871 /* Make exception for "NOT IMPLELEMENTED" string */ 2872 if (!strcmp(value,"NOT_IMPLEMENTED")) 2873 return(TRUE); 2874 2875 /* Check for bad, multicast, broadcast, or null address */ 2876 if (!ether_atoe(value, hwaddr) || 2877 (hwaddr[0] & 1) || 2878 (hwaddr[0] & hwaddr[1] & hwaddr[2] & hwaddr[3] & hwaddr[4] & hwaddr[5]) == 0xff || 2879 (hwaddr[0] | hwaddr[1] | hwaddr[2] | hwaddr[3] | hwaddr[4] | hwaddr[5]) == 0x00) { 2880 websBufferWrite(wp, "Invalid <b>%s</b> %s: not a MAC address<br>", 2881 v->longname, value); 2882 return FALSE; 2883 } 2884 2885 return TRUE; 2886} 2887 2888#ifdef __CONFIG_NAT__ 2889static void 2890validate_hwaddr(webs_t wp, char *value, struct variable *v, char *varname ) 2891{ 2892 2893 ret_code = EINVAL; 2894 2895 if (!valid_hwaddr(wp, value, v)) return; 2896 2897 if(varname ) 2898 nvram_set(varname,value); 2899 else 2900 nvram_set(v->name, value); 2901 2902 ret_code = 0; 2903 2904 2905} 2906#endif /* __CONFIG_NAT__ */ 2907 2908static void 2909validate_hwaddrs(webs_t wp, char *value, struct variable *v, char *varname ) 2910{ 2911 2912 assert(v); 2913 2914 ret_code = EINVAL; 2915 validate_list(wp, value, v, valid_hwaddr, varname); 2916} 2917 2918static void 2919validate_country(webs_t wp, char *value, struct variable *v, char *varname) 2920{ 2921 country_name_t *country=NULL; 2922 2923 assert(v); 2924 2925 ret_code = EINVAL; 2926 for(country = country_names; country->name; country++) 2927 if (!strcmp(value, country->abbrev)){ 2928 if (varname) 2929 nvram_set(varname,value); 2930 else 2931 nvram_set(v->name, value); 2932 ret_code = 0; 2933 return ; 2934 } 2935 websBufferWrite(wp, "Country abbreviation <b>%s</b>: is invalid<br>",value); 2936} 2937 2938static void 2939validate_dhcp(webs_t wp, char *value, struct variable *v, char *varname) 2940{ 2941 struct variable dhcp_variables[] = { 2942 { longname: "DHCP Server Starting LAN IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 2943 { longname: "DHCP Server Ending LAN IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 2944 }; 2945 char *start=NULL, *end=NULL; 2946 char dhcp_start[20]="dhcp_start"; 2947 char dhcp_end[20]="dhcp_start"; 2948 char lan_proto[20]="lan_proto"; 2949 char lan_ipaddr[20]="lan_ipaddr"; 2950 char lan_netmask[20]= "lan_netmask"; 2951 char *dhcp0_argv[3],*dhcp1_argv[3]; 2952 char index[5]; 2953 2954 assert(v); 2955 2956 ret_code = EINVAL; 2957 2958 memset(index,sizeof(index),0); 2959 /* fixup the nvram varnames if varname override is provided */ 2960 if (varname){ 2961 if (!get_index_string(v->prefix, 2962 varname,index,sizeof(index))) 2963 return; 2964 2965 snprintf(dhcp_start,sizeof(dhcp_start),"dhcp%s_start",index); 2966 snprintf(dhcp_end,sizeof(dhcp_end),"dhcp%s_end",index); 2967 snprintf(lan_proto,sizeof(lan_proto),"lan%s_proto",index); 2968 snprintf(lan_ipaddr,sizeof(lan_ipaddr),"lan%s_ipaddr",index); 2969 snprintf(lan_netmask,sizeof(lan_netmask),"lan%s_netmask",index); 2970 dhcp0_argv[0]=lan_ipaddr; 2971 dhcp0_argv[1]=lan_netmask; 2972 dhcp0_argv[2]=NULL; 2973 dhcp1_argv[0]=lan_ipaddr; 2974 dhcp1_argv[1]=lan_netmask; 2975 dhcp1_argv[2]=NULL; 2976 dhcp_variables[0].argv = dhcp0_argv; 2977 dhcp_variables[1].argv = dhcp1_argv; 2978 } 2979 2980 if (!(start = websGetVar(wp, dhcp_start, NULL)) || 2981 !(end = websGetVar(wp, dhcp_end, NULL))) 2982 return; 2983 if (!*start) start = end; 2984 if (!*end) end = start; 2985 if (!*start && !*end && !strcmp(nvram_safe_get(lan_proto), "dhcp")) { 2986 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a range<br>", v->longname); 2987 return; 2988 } 2989 if (!valid_ipaddr(wp, start, &dhcp_variables[0]) || 2990 !valid_ipaddr(wp, end, &dhcp_variables[1])) 2991 return; 2992 if (ntohl(inet_addr(start)) > ntohl(inet_addr(end))) { 2993 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 2994 dhcp_variables[0].longname, start, dhcp_variables[1].longname, end); 2995 return; 2996 } 2997 2998 nvram_set(dhcp_start, start); 2999 nvram_set(dhcp_end, end); 3000 3001 ret_code = 0; 3002} 3003 3004static void 3005validate_lan_ipaddr(webs_t wp, char *value, struct variable *v, char *varname) 3006{ 3007 struct variable fields[] = { 3008 { name: "lan_ipaddr", longname: "LAN IP Address" }, 3009 { name: "lan_netmask", longname: "LAN Subnet Mask" }, 3010 }; 3011 char *lan_ipaddr=NULL, *lan_netmask=NULL; 3012 char tmp_ipaddr[20], tmp_netmask[20]; 3013 struct in_addr ipaddr, netmask, netaddr, broadaddr; 3014 char lan_ipaddrs[][20] = { "dhcp_start", "dhcp_end", "dmz_ipaddr" }; 3015#ifdef __CONFIG_NAT__ 3016 netconf_filter_t start, end; 3017 netconf_nat_t nat; 3018 bool valid; 3019#endif /* __CONFIG_NAT__ */ 3020 int i; 3021 3022 assert(v); 3023 3024 ret_code = EINVAL; 3025 3026 /* Insert name overrides */ 3027 if (varname) 3028 { 3029 char index[5]; 3030 3031 if (!get_index_string(v->prefix, 3032 varname,index,sizeof(index))) 3033 return ; 3034 3035 snprintf(tmp_ipaddr,sizeof(tmp_ipaddr),"lan%s_ipaddr",index); 3036 snprintf(tmp_netmask,sizeof(tmp_netmask),"lan%s_netmask",index); 3037 fields[0].name = tmp_ipaddr; 3038 fields[1].name = tmp_netmask; 3039 snprintf(lan_ipaddrs[0],sizeof(lan_ipaddrs[0]),"dhcp%s_start",index); 3040 snprintf(lan_ipaddrs[1],sizeof(lan_ipaddrs[1]),"dhcp%s_end",index); 3041 } 3042 /* Basic validation */ 3043 if (!(lan_ipaddr = websGetVar(wp, fields[0].name, NULL)) || 3044 !(lan_netmask = websGetVar(wp, fields[1].name, NULL)) || 3045 !valid_ipaddr(wp, lan_ipaddr, &fields[0]) || 3046 !valid_ipaddr(wp, lan_netmask, &fields[1])) 3047 return; 3048 3049 /* Check for broadcast or network address */ 3050 (void) inet_aton(lan_ipaddr, &ipaddr); 3051 (void) inet_aton(lan_netmask, &netmask); 3052 netaddr.s_addr = ipaddr.s_addr & netmask.s_addr; 3053 broadaddr.s_addr = netaddr.s_addr | ~netmask.s_addr; 3054 if (ipaddr.s_addr == netaddr.s_addr) { 3055 websBufferWrite(wp, "Invalid <b>%s</b> %s: cannot be the network address<br>", 3056 fields[0].longname, lan_ipaddr); 3057 return; 3058 } 3059 if (ipaddr.s_addr == broadaddr.s_addr) { 3060 websBufferWrite(wp, "Invalid <b>%s</b> %s: cannot be the broadcast address<br>", 3061 fields[0].longname, lan_ipaddr); 3062 return; 3063 } 3064 3065 3066 nvram_set(fields[0].name, lan_ipaddr); 3067 nvram_set(fields[1].name, lan_netmask); 3068 3069 3070 /* Fix up LAN IP addresses */ 3071 for (i = 0; i < ARRAYSIZE(lan_ipaddrs); i++) { 3072 3073 value = nvram_get(lan_ipaddrs[i]); 3074 if (value && *value) { 3075 (void) inet_aton(value, &ipaddr); 3076 ipaddr.s_addr &= ~netmask.s_addr; 3077 ipaddr.s_addr |= netaddr.s_addr; 3078 3079 nvram_set(lan_ipaddrs[i], inet_ntoa(ipaddr)); 3080 } 3081 } 3082 3083#ifdef __CONFIG_NAT__ 3084 /* Fix up client filters and port forwards */ 3085 for (i = 0; i < MAX_NVPARSE; i++) { 3086 if (get_filter_client(i, &start, &end)) { 3087 start.match.src.ipaddr.s_addr &= ~netmask.s_addr; 3088 start.match.src.ipaddr.s_addr |= netaddr.s_addr; 3089 end.match.src.ipaddr.s_addr &= ~netmask.s_addr; 3090 end.match.src.ipaddr.s_addr |= netaddr.s_addr; 3091 3092 valid = set_filter_client(i, &start, &end); 3093 a_assert(valid); 3094 } 3095 if (get_forward_port(i, &nat)) { 3096 nat.ipaddr.s_addr &= ~netmask.s_addr; 3097 nat.ipaddr.s_addr |= netaddr.s_addr; 3098 valid = set_forward_port(i, &nat); 3099 a_assert(valid); 3100 } 3101 } 3102#endif /* __CONFIG_NAT__ */ 3103 3104 ret_code = 0; 3105} 3106 3107#ifdef __CONFIG_NAT__ 3108static void 3109validate_filter_client(webs_t wp, char *value, struct variable *v, char *varname) 3110{ 3111 int n, i, j; 3112 bool valid; 3113 struct variable fields[] = { 3114 { name: "filter_client_from_start%d", longname: "LAN Client Filter Starting IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 3115 { name: "filter_client_from_end%d", longname: "LAN Client Filter Ending IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 3116 { name: "filter_client_proto%d", longname: "LAN Client Filter Protocol", argv: ARGV("tcp", "udp") }, 3117 { name: "filter_client_to_start%d", longname: "LAN Client Filter Starting Destination Port", argv: ARGV("0", "65535") }, 3118 { name: "filter_client_to_end%d", longname: "LAN Client Filter Ending Destination Port", argv: ARGV("0", "65535") }, 3119 { name: "filter_client_from_day%d", longname: "LAN Client Filter Starting Day", argv: ARGV("0", "6") }, 3120 { name: "filter_client_to_day%d", longname: "LAN Client Filter Ending Day", argv: ARGV("0", "6") }, 3121 { name: "filter_client_from_sec%d", longname: "LAN Client Filter Starting Second", argv: ARGV("0", "86400") }, 3122 { name: "filter_client_to_sec%d", longname: "LAN Client Filter Ending Second", argv: ARGV("0", "86400") }, 3123 }; 3124 char *from_start=NULL, *from_end=NULL, *proto=NULL, *to_start=NULL; 3125 char *to_end=NULL, *from_day=NULL, *to_day=NULL, *from_sec=NULL, *to_sec=NULL, *enable=NULL; 3126 char **locals[] = { &from_start, &from_end, &proto, &to_start, &to_end, &from_day, &to_day, &from_sec, &to_sec }; 3127 char name[1000]; 3128 netconf_filter_t start, end; 3129 3130 assert(v); 3131 3132 ret_code = EINVAL; 3133 3134 /* filter_client indicates how many to expect */ 3135 if (!valid_range(wp, value, v)){ 3136 websBufferWrite(wp, "Invalid filter client string <b>%s</b><br>",value); 3137 return; 3138 } 3139 n = atoi(value); 3140 3141 for (i = 0; i <= n; i++) { 3142 /* Set up field names */ 3143 for (j = 0; j < ARRAYSIZE(fields); j++) { 3144 snprintf(name, sizeof(name), fields[j].name, i); 3145 if (!(*locals[j] = websGetVar(wp, name, NULL))) 3146 break; 3147 } 3148 /* Incomplete web page */ 3149 if (j < ARRAYSIZE(fields)) 3150 continue; 3151 /* Enable is a checkbox */ 3152 snprintf(name, sizeof(name), "filter_client_enable%d", i); 3153 if (websGetVar(wp, name, NULL)) 3154 enable = "on"; 3155 else 3156 enable = "off"; 3157 /* Delete entry if all fields are blank */ 3158 if (!*from_start && !*from_end && !*to_start && !*to_end) { 3159 del_filter_client(i); 3160 continue; 3161 } 3162 /* Fill in empty fields with default values */ 3163 if (!*from_start) from_start = from_end; 3164 if (!*from_end) from_end = from_start; 3165 if (!*to_start) to_start = to_end; 3166 if (!*to_end) to_end = to_start; 3167 if (!*from_start || !*from_end) { 3168 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN IP Address Range<br>", v->longname); 3169 continue; 3170 } 3171 if (!*to_start || !*to_end) { 3172 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a Destination Port Range<br>", v->longname); 3173 continue; 3174 } 3175 /* Check individual fields */ 3176 if (!valid_ipaddr(wp, from_start, &fields[0]) || 3177 !valid_ipaddr(wp, from_end, &fields[1]) || 3178 !valid_choice(wp, proto, &fields[2]) || 3179 !valid_range(wp, to_start, &fields[3]) || 3180 !valid_range(wp, to_end, &fields[4]) || 3181 !valid_range(wp, from_day, &fields[5]) || 3182 !valid_range(wp, to_day, &fields[6]) || 3183 !valid_range(wp, from_sec, &fields[7]) || 3184 !valid_range(wp, to_sec, &fields[8])) 3185 continue; 3186 /* Check dependencies between fields */ 3187 if (ntohl(inet_addr(from_start)) > ntohl(inet_addr(from_end))) { 3188 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 3189 fields[0].longname, from_start, fields[1].longname, from_end); 3190 continue; 3191 } 3192 if (atoi(to_start) > atoi(to_end)) { 3193 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 3194 fields[3].longname, to_start, fields[4].longname, to_end); 3195 continue; 3196 } 3197 3198 /* Set up parameters */ 3199 memset(&start, 0, sizeof(netconf_filter_t)); 3200 if (!strcmp(proto, "tcp")) 3201 start.match.ipproto = IPPROTO_TCP; 3202 else if (!strcmp(proto, "udp")) 3203 start.match.ipproto = IPPROTO_UDP; 3204 (void) inet_aton(from_start, &start.match.src.ipaddr); 3205 start.match.src.netmask.s_addr = htonl(0xffffffff); 3206 start.match.dst.ports[0] = htons(atoi(to_start)); 3207 start.match.dst.ports[1] = htons(atoi(to_end)); 3208 start.match.days[0] = atoi(from_day); 3209 start.match.days[1] = atoi(to_day); 3210 start.match.secs[0] = atoi(from_sec); 3211 start.match.secs[1] = atoi(to_sec); 3212 if (!strcmp(enable, "off")) 3213 start.match.flags |= NETCONF_DISABLED; 3214 memcpy(&end, &start, sizeof(netconf_filter_t)); 3215 (void) inet_aton(from_end, &end.match.src.ipaddr); 3216 3217 /* Do it */ 3218 valid = set_filter_client(i, &start, &end); 3219 a_assert(valid); 3220 } 3221 3222 ret_code = 0; 3223} 3224 3225static void 3226validate_forward_port(webs_t wp, char *value, struct variable *v, char *varname) 3227{ 3228 int n, i, j; 3229 bool valid; 3230 struct variable fields[] = { 3231 { name: "forward_port_proto%d", longname: "Port Forward Protocol", argv: ARGV("tcp", "udp") }, 3232 { name: "forward_port_from_start%d", longname: "Port Forward Starting WAN Port", argv: ARGV("0", "65535") }, 3233 { name: "forward_port_from_end%d", longname: "Port Forward Ending WAN Port", argv: ARGV("0", "65535") }, 3234 { name: "forward_port_to_ip%d", longname: "Port Forward LAN IP Address", argv: ARGV("lan_ipaddr", "lan_netmask") }, 3235 { name: "forward_port_to_start%d", longname: "Port Forward Starting LAN Port", argv: ARGV("0", "65535") }, 3236 { name: "forward_port_to_end%d", longname: "Port Forward Ending LAN Port", argv: ARGV("0", "65535") }, 3237 }; 3238 char *proto=NULL, *from_start=NULL, *from_end=NULL; 3239 char *to_ip=NULL, *to_start=NULL, *to_end=NULL, *enable=NULL; 3240 char **locals[] = { &proto, &from_start, &from_end, &to_ip, &to_start, &to_end }; 3241 char name[1000]; 3242 netconf_nat_t nat; 3243 3244 assert(v); 3245 3246 ret_code = EINVAL; 3247 3248 /* forward_port indicates how many to expect */ 3249 if (!valid_range(wp, value, v)){ 3250 websBufferWrite(wp, "Invalid forward port string <b>%s</b><br>",value); 3251 return; 3252 } 3253 n = atoi(value); 3254 3255 for (i = 0; i <= n; i++) { 3256 /* Set up field names */ 3257 for (j = 0; j < ARRAYSIZE(fields); j++) { 3258 snprintf(name, sizeof(name), fields[j].name, i); 3259 if (!(*locals[j] = websGetVar(wp, name, NULL))) 3260 break; 3261 } 3262 /* Incomplete web page */ 3263 if (j < ARRAYSIZE(fields)) 3264 continue; 3265 /* Enable is a checkbox */ 3266 snprintf(name, sizeof(name), "forward_port_enable%d", i); 3267 if (websGetVar(wp, name, NULL)) 3268 enable = "on"; 3269 else 3270 enable = "off"; 3271 /* Delete entry if all fields are blank */ 3272 if (!*from_start && !*from_end && !*to_ip && !*to_start && !*to_end) { 3273 del_forward_port(i); 3274 continue; 3275 } 3276 /* Fill in empty fields with default values */ 3277 if (!*from_start) from_start = from_end; 3278 if (!*from_end) from_end = from_start; 3279 if (!*to_start && !*to_end) 3280 to_start = from_start; 3281 if (!*to_start) to_start = to_end; 3282 if (!*to_end) to_end = to_start; 3283 if (!*from_start || !*from_end) { 3284 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN IP Address Range<br>", v->longname); 3285 continue; 3286 } 3287 if (!*to_ip) { 3288 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a LAN IP Address<br>", v->longname); 3289 continue; 3290 } 3291 if (!*to_start || !*to_end) { 3292 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a Destination Port Range<br>", v->longname); 3293 continue; 3294 } 3295 /* Check individual fields */ 3296 if (!valid_choice(wp, proto, &fields[0]) || 3297 !valid_range(wp, from_start, &fields[1]) || 3298 !valid_range(wp, from_end, &fields[2]) || 3299 !valid_ipaddr(wp, to_ip, &fields[3]) || 3300 !valid_range(wp, to_start, &fields[4]) || 3301 !valid_range(wp, to_end, &fields[5])) 3302 continue; 3303 if (atoi(from_start) > atoi(from_end)) { 3304 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 3305 fields[1].longname, from_start, fields[2].longname, from_end); 3306 continue; 3307 } 3308 if (atoi(to_start) > atoi(to_end)) { 3309 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 3310 fields[4].longname, to_start, fields[5].longname, to_end); 3311 continue; 3312 } 3313 if ((atoi(from_end) - atoi(from_start)) != (atoi(to_end) - atoi(to_start))) { 3314 websBufferWrite(wp, "Invalid <b>%s</b>: WAN Port Range and LAN Port Range must be the same size<br>", v->longname); 3315 continue; 3316 } 3317 3318 /* Set up parameters */ 3319 memset(&nat, 0, sizeof(netconf_nat_t)); 3320 if (!strcmp(proto, "tcp")) 3321 nat.match.ipproto = IPPROTO_TCP; 3322 else if (!strcmp(proto, "udp")) 3323 nat.match.ipproto = IPPROTO_UDP; 3324 nat.match.dst.ports[0] = htons(atoi(from_start)); 3325 nat.match.dst.ports[1] = htons(atoi(from_end)); 3326 (void) inet_aton(to_ip, &nat.ipaddr); 3327 nat.ports[0] = htons(atoi(to_start)); 3328 nat.ports[1] = htons(atoi(to_end)); 3329 if (!strcmp(enable, "off")) 3330 nat.match.flags |= NETCONF_DISABLED; 3331 3332 /* Do it */ 3333 valid = set_forward_port(i, &nat); 3334 a_assert(valid); 3335 } 3336 ret_code =0; 3337} 3338 3339static void 3340validate_autofw_port(webs_t wp, char *value, struct variable *v, char *varname) 3341{ 3342 int n, i, j; 3343 bool valid; 3344 struct variable fields[] = { 3345 { name: "autofw_port_out_proto%d", longname: "Outbound Protocol", argv: ARGV("tcp", "udp") }, 3346 { name: "autofw_port_out_start%d", longname: "Outbound Port Start", argv: ARGV("0", "65535") }, 3347 { name: "autofw_port_out_end%d", longname: "Outbound Port End", argv: ARGV("0", "65535") }, 3348 { name: "autofw_port_in_proto%d", longname: "Inbound Protocol", argv: ARGV("tcp", "udp") }, 3349 { name: "autofw_port_in_start%d", longname: "Inbound Port Start", argv: ARGV("0", "65535") }, 3350 { name: "autofw_port_in_end%d", longname: "Inbound Port End", argv: ARGV("0", "65535") }, 3351 { name: "autofw_port_to_start%d", longname: "To Port Start", argv: ARGV("0", "65535") }, 3352 { name: "autofw_port_to_end%d", longname: "To Port End", argv: ARGV("0", "65535") }, 3353 }; 3354 char *out_proto=NULL, *out_start=NULL, *out_end=NULL, *in_proto=NULL; 3355 char *in_start=NULL, *in_end=NULL, *to_start=NULL, *to_end=NULL, *enable=NULL; 3356 char **locals[] = { &out_proto, &out_start, &out_end, &in_proto, &in_start, &in_end, &to_start, &to_end }; 3357 char name[1000]; 3358 netconf_app_t app; 3359 3360 assert(v); 3361 3362 ret_code = EINVAL; 3363 3364 /* autofw_port indicates how many to expect */ 3365 if (!valid_range(wp, value, v)){ 3366 websBufferWrite(wp, "Invalid auto forward port string <b>%s</b><br>",value); 3367 return; 3368 } 3369 n = atoi(value); 3370 3371 for (i = 0; i <= n; i++) { 3372 /* Set up field names */ 3373 for (j = 0; j < ARRAYSIZE(fields); j++) { 3374 snprintf(name, sizeof(name), fields[j].name, i); 3375 if (!(*locals[j] = websGetVar(wp, name, NULL))) 3376 break; 3377 } 3378 /* Incomplete web page */ 3379 if (j < ARRAYSIZE(fields)) 3380 continue; 3381 /* Enable is a checkbox */ 3382 snprintf(name, sizeof(name), "autofw_port_enable%d", i); 3383 if (websGetVar(wp, name, NULL)) 3384 enable = "on"; 3385 else 3386 enable = "off"; 3387 /* Delete entry if all fields are blank */ 3388 if (!*out_start && !*out_end && !*in_start && !*in_end && !*to_start && !*to_end) { 3389 del_autofw_port(i); 3390 continue; 3391 } 3392 /* Fill in empty fields with default values */ 3393 if (!*out_start) out_start = out_end; 3394 if (!*out_end) out_end = out_start; 3395 if (!*in_start) in_start = in_end; 3396 if (!*in_end) in_end = in_start; 3397 if (!*to_start && !*to_end) 3398 to_start = in_start; 3399 if (!*to_start) to_start = to_end; 3400 if (!*to_end) to_end = to_start; 3401 if (!*out_start || !*out_end) { 3402 websBufferWrite(wp, "Invalid <b>%s</b>: must specify an Outbound Port Range<br>", v->longname); 3403 continue; 3404 } 3405 if (!*in_start || !*in_end) { 3406 websBufferWrite(wp, "Invalid <b>%s</b>: must specify an Inbound Port Range<br>", v->longname); 3407 continue; 3408 } 3409 if (!*to_start || !*to_end) { 3410 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a To Port Range<br>", v->longname); 3411 continue; 3412 } 3413 /* Check individual fields */ 3414 if (!valid_choice(wp, out_proto, &fields[0]) || 3415 !valid_range(wp, out_start, &fields[1]) || 3416 !valid_range(wp, out_end, &fields[2]) || 3417 !valid_choice(wp, in_proto, &fields[3]) || 3418 !valid_range(wp, in_start, &fields[4]) || 3419 !valid_range(wp, in_end, &fields[5]) || 3420 !valid_range(wp, to_start, &fields[6]) || 3421 !valid_range(wp, to_end, &fields[7])) 3422 continue; 3423 /* Check dependencies between fields */ 3424 if (atoi(out_start) > atoi(out_end)) { 3425 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 3426 fields[1].longname, out_start, fields[2].longname, out_end); 3427 continue; 3428 } 3429 if (atoi(in_start) > atoi(in_end)) { 3430 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 3431 fields[4].longname, in_start, fields[5].longname, in_end); 3432 continue; 3433 } 3434 if (atoi(to_start) > atoi(to_end)) { 3435 websBufferWrite(wp, "Invalid <b>%s</b> %s: greater than <b>%s</b> %s<br>", 3436 fields[6].longname, in_start, fields[7].longname, in_end); 3437 continue; 3438 } 3439 if ((atoi(in_end) - atoi(in_start)) != (atoi(to_end) - atoi(to_start))) { 3440 websBufferWrite(wp, "Invalid <b>%s</b>: Inbound Port Range and To Port Range must be the same size<br>", v->longname); 3441 continue; 3442 } 3443#ifdef NEW_PORT_TRIG 3444 if ((atoi(in_end) - atoi(in_start)) > 100) { 3445 websBufferWrite(wp, "Invalid <b>%s</b>: Inbound Port Range must be less than 100<br>", v->longname); 3446 continue; 3447 } 3448#endif 3449 3450 /* Set up parameters */ 3451 memset(&app, 0, sizeof(netconf_app_t)); 3452 if (!strcmp(out_proto, "tcp")) 3453 app.match.ipproto = IPPROTO_TCP; 3454 else if (!strcmp(out_proto, "udp")) 3455 app.match.ipproto = IPPROTO_UDP; 3456 app.match.dst.ports[0] = htons(atoi(out_start)); 3457 app.match.dst.ports[1] = htons(atoi(out_end)); 3458 if (!strcmp(in_proto, "tcp")) 3459 app.proto = IPPROTO_TCP; 3460 else if (!strcmp(in_proto, "udp")) 3461 app.proto = IPPROTO_UDP; 3462 app.dport[0] = htons(atoi(in_start)); 3463 app.dport[1] = htons(atoi(in_end)); 3464 app.to[0] = htons(atoi(to_start)); 3465 app.to[1] = htons(atoi(to_end)); 3466 if (!strcmp(enable, "off")) 3467 app.match.flags |= NETCONF_DISABLED; 3468 3469 /* Do it */ 3470 valid = set_autofw_port(i, &app); 3471 a_assert(valid); 3472 } 3473 ret_code = 0; 3474} 3475#endif /* __CONFIG_NAT__ */ 3476 3477static void 3478validate_lan_route(webs_t wp, char *value, struct variable *v, char *varname) 3479{ 3480 int n, i; 3481 char buf[1000] = "", *cur = buf; 3482 char lan_ipaddr[20] ="lan_ipaddr"; 3483 char lan_netmask[20]="lan_netmask"; 3484 char *lan_argv[3]; 3485 3486 struct variable lan_route_variables[] = { 3487 { longname: "Route IP Address", argv: NULL }, 3488 { longname: "Route Subnet Mask", argv: NULL }, 3489 { longname: "Route Gateway", argv: NULL }, 3490 { longname: "Route Metric", argv: ARGV("0", "15") }, 3491 }; 3492 3493 assert(v); 3494 3495 ret_code = EINVAL; 3496 3497 /* Insert name overrides */ 3498 if (varname) 3499 { 3500 char index[5]; 3501 3502 if (!get_index_string(v->prefix,varname, 3503 index,sizeof(index))) 3504 return; 3505 3506 snprintf(lan_ipaddr,sizeof(lan_ipaddr),"lan%s_ipaddr",index); 3507 snprintf(lan_netmask,sizeof(lan_netmask),"lan%s_netmask",index); 3508 } 3509 3510 n = atoi(value); 3511 3512 for (i = 0; i < n; i++) { 3513 char lan_route_ipaddr[] = "lan_route_ipaddrXXX"; 3514 char lan_route_netmask[] = "lan_route_netmaskXXX"; 3515 char lan_route_gateway[] = "lan_route_gatewayXXX"; 3516 char lan_route_metric[] = "lan_route_metricXXX"; 3517 char *ipaddr, *netmask, *gateway, *metric; 3518 3519 snprintf(lan_route_ipaddr, sizeof(lan_route_ipaddr), "%s_ipaddr%d", v->name, i); 3520 snprintf(lan_route_netmask, sizeof(lan_route_netmask), "%s_netmask%d", v->name, i); 3521 snprintf(lan_route_gateway, sizeof(lan_route_gateway), "%s_gateway%d", v->name, i); 3522 snprintf(lan_route_metric, sizeof(lan_route_metric), "%s_metric%d", v->name, i); 3523 if (!(ipaddr = websGetVar(wp, lan_route_ipaddr, NULL)) || 3524 !(netmask = websGetVar(wp, lan_route_netmask, NULL)) || 3525 !(gateway = websGetVar(wp, lan_route_gateway, NULL)) || 3526 !(metric = websGetVar(wp, lan_route_metric, NULL))) 3527 return; 3528 if (!*ipaddr && !*netmask && !*gateway && !*metric) 3529 continue; 3530 if (!*ipaddr && !*netmask && *gateway) { 3531 ipaddr = "0.0.0.0"; 3532 netmask = "0.0.0.0"; 3533 } 3534 if (!*gateway) 3535 gateway = "0.0.0.0"; 3536 if (!*metric) 3537 metric = "0"; 3538 if (!*ipaddr) { 3539 websBufferWrite(wp, "Invalid <b>%s</b>: must specify an IP Address<br>", v->longname); 3540 continue; 3541 } 3542 if (!*netmask) { 3543 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a Subnet Mask<br>", v->longname); 3544 continue; 3545 } 3546 3547 lan_argv[0]=lan_ipaddr; 3548 lan_argv[1]=lan_netmask; 3549 lan_argv[2]=NULL; 3550 3551 lan_route_variables[2].argv = lan_argv; 3552 if (!valid_ipaddr(wp, ipaddr, &lan_route_variables[0]) || 3553 !valid_ipaddr(wp, netmask, &lan_route_variables[1]) || 3554 !valid_ipaddr(wp, gateway, &lan_route_variables[2]) || 3555 !valid_range(wp, metric, &lan_route_variables[3])) 3556 continue; 3557 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s:%s:%s:%s", 3558 cur == buf ? "" : " ", ipaddr, netmask, gateway, metric); 3559 } 3560 3561 if (varname) 3562 nvram_set(varname,buf); 3563 else 3564 nvram_set(v->name, buf); 3565 ret_code = 0; 3566} 3567 3568#ifdef __CONFIG_NAT__ 3569static void 3570validate_wan_route(webs_t wp, char *value, struct variable *v, char *varname) 3571{ 3572 int n, i; 3573 char buf[1000] = "", *cur = buf; 3574 struct variable wan_route_variables[] = { 3575 { longname: "Route IP Address", argv: NULL }, 3576 { longname: "Route Subnet Mask", argv: NULL }, 3577 { longname: "Route Gateway", argv: NULL }, 3578 { longname: "Route Metric", argv: ARGV("0", "15") }, 3579 }; 3580 3581 assert(v); 3582 3583 ret_code = EINVAL; 3584 3585 n = atoi(value); 3586 3587 for (i = 0; i < n; i++) { 3588 char wan_route_ipaddr[] = "wan_route_ipaddrXXX"; 3589 char wan_route_netmask[] = "wan_route_netmaskXXX"; 3590 char wan_route_gateway[] = "wan_route_gatewayXXX"; 3591 char wan_route_metric[] = "wan_route_metricXXX"; 3592 char *ipaddr, *netmask, *gateway, *metric; 3593 3594 snprintf(wan_route_ipaddr, sizeof(wan_route_ipaddr), "%s_ipaddr%d", v->name, i); 3595 snprintf(wan_route_netmask, sizeof(wan_route_netmask), "%s_netmask%d", v->name, i); 3596 snprintf(wan_route_gateway, sizeof(wan_route_gateway), "%s_gateway%d", v->name, i); 3597 snprintf(wan_route_metric, sizeof(wan_route_metric), "%s_metric%d", v->name, i); 3598 if (!(ipaddr = websGetVar(wp, wan_route_ipaddr, NULL)) || 3599 !(netmask = websGetVar(wp, wan_route_netmask, NULL)) || 3600 !(gateway = websGetVar(wp, wan_route_gateway, NULL)) || 3601 !(metric = websGetVar(wp, wan_route_metric, NULL))) 3602 continue; 3603 if (!*ipaddr && !*netmask && !*gateway && !*metric) 3604 continue; 3605 if (!*ipaddr && !*netmask && *gateway) { 3606 ipaddr = "0.0.0.0"; 3607 netmask = "0.0.0.0"; 3608 } 3609 if (!*gateway) 3610 gateway = "0.0.0.0"; 3611 if (!*metric) 3612 metric = "0"; 3613 if (!*ipaddr) { 3614 websBufferWrite(wp, "Invalid <b>%s</b>: must specify an IP Address<br>", v->longname); 3615 continue; 3616 } 3617 if (!*netmask) { 3618 websBufferWrite(wp, "Invalid <b>%s</b>: must specify a Subnet Mask<br>", v->longname); 3619 continue; 3620 } 3621 if (!valid_ipaddr(wp, ipaddr, &wan_route_variables[0]) || 3622 !valid_ipaddr(wp, netmask, &wan_route_variables[1]) || 3623 !valid_ipaddr(wp, gateway, &wan_route_variables[2]) || 3624 !valid_range(wp, metric, &wan_route_variables[3])) 3625 continue; 3626 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s:%s:%s:%s", 3627 cur == buf ? "" : " ", ipaddr, netmask, gateway, metric); 3628 } 3629 3630 3631 nvram_set(v->name, buf); 3632 3633 ret_code = 0; 3634} 3635#endif /* __CONFIG_NAT__ */ 3636 3637static void 3638validate_wl_auth(webs_t wp, char *value, struct variable *v, char *varname) 3639{ 3640 3641 assert(v); 3642 3643 ret_code = EINVAL; 3644 3645 if (!valid_choice(wp, value, v)){ 3646 websBufferWrite(wp, "Invalid auth value string <b>%s</b><br>",value); 3647 return; 3648 } 3649 3650 if (!strcmp(value, "1")) { 3651 char *wep = websGetVar(wp, "wl_wep", ""); 3652 if (!wep || strcmp(wep, "enabled")) { 3653 websBufferWrite(wp, "Invalid <b>WEP Encryption</b>: must be <b>Enabled</b> when <b>802.11 Authentication</b> is <b>%s</b><br>", value); 3654 return; 3655 } 3656 } 3657 3658 if (varname) 3659 nvram_set(varname, value); 3660 else 3661 nvram_set(v->name, value); 3662 ret_code = 0; 3663} 3664 3665static void 3666validate_wl_preauth(webs_t wp, char *value, struct variable *v, char *varname) 3667{ 3668 char *ptr=NULL; 3669 3670 assert(v); 3671 3672 ptr =( (varname) ? varname : v->name ); 3673 3674 if (!strcmp(value, "disabled")) 3675 nvram_set(ptr, "0"); 3676 else 3677 nvram_set(ptr, "1"); 3678 3679 ret_code =0; 3680 3681 return; 3682} 3683 3684static void 3685validate_wl_auth_mode(webs_t wp, char *value, struct variable *v, char *varname) 3686{ 3687 3688 assert(v); 3689 3690 ret_code = EINVAL; 3691 3692 if (!valid_choice(wp, value, v)){ 3693 websBufferWrite(wp, "Invalid auto mode string <b>%s</b>",value); 3694 return; 3695 } 3696 3697 if (!strcmp(value, "radius")) { 3698 char *wep = websGetVar(wp, "wl_wep", ""); 3699 char *ipaddr = websGetVar(wp, "wl_radius_ipaddr", ""); 3700 if (!wep || strcmp(wep, "enabled")) { 3701 websBufferWrite(wp, "Invalid <b>WEP Encryption</b>: must be <b>Enabled</b> when <b>Network Authentication</b> is <b>%s</b><br>", value); 3702 return; 3703 } 3704 if (!ipaddr || !strcmp(ipaddr, "")) { 3705 websBufferWrite(wp, "Invalid <b>%s</b>: must first specify a valid <b>RADIUS Server</b><br>", v->longname); 3706 return; 3707 } 3708 } 3709 3710 if (varname) 3711 nvram_set(varname, value); 3712 else 3713 nvram_set(v->name, value); 3714 3715 ret_code = 0; 3716 3717} 3718 3719static void 3720validate_wl_akm(webs_t wp, char *value, struct variable *v, char *varname) 3721{ 3722 char akms[WLC_IOCTL_SMLEN] = ""; 3723 char *wpa=NULL, *psk=NULL; 3724#ifdef BCMWPA2 3725 char *wpa2=NULL, *psk2=NULL; 3726#endif 3727 3728 assert(v); 3729 3730 ret_code = EINVAL; 3731 3732 wpa = websGetVar(wp, "wl_akm_wpa", NULL); 3733 if( !wpa ) 3734 wpa = "disabled"; 3735 psk = websGetVar(wp, "wl_akm_psk", NULL); 3736#ifdef BCMWPA2 3737 wpa2 = websGetVar(wp, "wl_akm_wpa2", NULL); 3738 if( !wpa2 ) 3739 wpa2 = "disabled"; 3740 psk2 = websGetVar(wp, "wl_akm_psk2", NULL); 3741#endif 3742 if (!wpa || !psk 3743#ifdef BCMWPA2 3744 || !wpa2 || !psk2 3745#endif 3746 ) { 3747 ret_code = 0; 3748 return; 3749 } 3750 3751 if (!strcmp(wpa, "enabled") 3752#ifdef BCMWPA2 3753 || !strcmp(wpa2, "enabled") 3754#endif /* BCMWPA2 */ 3755 ) { 3756 char *ipaddr = websGetVar(wp, "wl_radius_ipaddr", ""); 3757 if (!ipaddr || !strcmp(ipaddr, "")) { 3758 websBufferWrite(wp, "Invalid <b>%s</b>: must first specify a valid <b>RADIUS Server</b><br>", v->longname); 3759 return; 3760 } 3761 } 3762 3763 if (!strcmp(psk, "enabled") 3764#ifdef BCMWPA2 3765 || !strcmp(psk2, "enabled") 3766#endif /* BCMWPA2 */ 3767 ) { 3768 char *key = websGetVar(wp, "wl_wpa_psk", ""); 3769 if (!key || !strcmp(key, "")) { 3770 websBufferWrite(wp, "Invalid <b>%s</b>: must first specify a valid <b>WPA Pre-Shared Key</b><br>", v->longname); 3771 return; 3772 } 3773 } 3774 3775 if (!strcmp(wpa, "enabled") || !strcmp(psk, "enabled") 3776#ifdef BCMWPA2 3777 || !strcmp(wpa2, "enabled") || !strcmp(psk2, "enabled") 3778#endif /* BCMWPA2 */ 3779 ) { 3780 char *crypto = websGetVar(wp, "wl_crypto", ""); 3781 if (!crypto || (strcmp(crypto, "tkip") && strcmp(crypto, "aes") && 3782 strcmp(crypto, "tkip+aes"))) { 3783 websBufferWrite(wp, "Invalid <b>%s</b>: <b>Crypto Algorithm</b> mode must be TKIP or AES or TKIP+AES<br>", v->longname); 3784 return; 3785 } 3786 } 3787 3788 if (!strcmp(wpa, "enabled")) 3789 strcat(akms, "wpa "); 3790 if (!strcmp(psk, "enabled")) 3791 strcat(akms, "psk "); 3792#ifdef BCMWPA2 3793 if (!strcmp(wpa2, "enabled")) 3794 strcat(akms, "wpa2 "); 3795 if (!strcmp(psk2, "enabled")) 3796 strcat(akms, "psk2 "); 3797#endif 3798 if (varname) 3799 nvram_set(varname, akms); 3800 else 3801 nvram_set("wl_akm", akms); 3802 3803 ret_code = 0; 3804} 3805 3806static void 3807validate_wl_wpa_psk(webs_t wp, char *value, struct variable *v, char *varname) 3808{ 3809 int len = strlen(value); 3810 char *c=NULL; 3811 3812 assert(v); 3813 3814 ret_code = EINVAL; 3815 3816 if (len == 64) { 3817 for (c = value; *c; c++) { 3818 if (!isxdigit((int) *c)) { 3819 websBufferWrite(wp, "Invalid <b>%s</b>: character %c is not a hexadecimal digit<br>", v->longname, *c); 3820 return; 3821 } 3822 } 3823 } else if (len < 8 || len > 63) { 3824 websBufferWrite(wp, "Invalid <b>%s</b>: must be between 8 and 63 ASCII characters or 64 hexadecimal digits<br>", v->longname); 3825 return; 3826 } 3827 3828 if (varname) 3829 nvram_set(varname, value); 3830 else 3831 nvram_set(v->name, value); 3832 3833 ret_code = 0; 3834} 3835 3836static void 3837validate_wl_key(webs_t wp, char *value, struct variable *v, char *varname) 3838{ 3839 char *c=NULL; 3840 3841 assert(v); 3842 3843 ret_code = EINVAL; 3844 3845 switch (strlen(value)) { 3846 case 5: 3847 case 13: 3848 break; 3849 case 10: 3850 case 26: 3851 for (c = value; *c; c++) { 3852 if (!isxdigit((int) *c)) { 3853 websBufferWrite(wp, "Invalid <b>%s</b>: character %c is not a hexadecimal digit<br>", v->longname, *c); 3854 return; 3855 } 3856 } 3857 break; 3858 default: 3859 websBufferWrite(wp, "Invalid <b>%s</b>: must be 5 or 13 ASCII characters or 10 or 26 hexadecimal digits<br>", v->longname); 3860 return; 3861 } 3862 3863 if (varname) 3864 nvram_set(varname, value); 3865 else 3866 nvram_set(v->name, value); 3867 3868 ret_code = 0; 3869} 3870 3871static void 3872validate_wl_wep(webs_t wp, char *value, struct variable *v, char *varname) 3873{ 3874 char *auth_mode=NULL,*name=NULL, *auth=NULL; 3875 3876 assert(v); 3877 3878 ret_code = EINVAL; 3879 3880 if (!valid_choice(wp, value, v)){ 3881 websBufferWrite(wp, "Invalid wep string <b>%s</b>",value); 3882 return; 3883 } 3884 if (varname) 3885 name = varname; 3886 else 3887 name = v->name; 3888 3889 auth = websGetVar(wp, "wl_auth", NULL); 3890 auth_mode = websGetVar(wp, "wl_auth_mode", NULL); 3891 if (!strcmp(value, "enabled")) { 3892 if (!auth_mode || strcmp(auth_mode, "radius")) { 3893 char wl_key[] = "wl_keyXXX"; 3894 char wl_key_index[] = "wl_keyXXX"; 3895 3896 if (varname){ 3897 char index[5]; 3898 if (!get_index_string(v->prefix,varname,index,sizeof(index))) 3899 return; 3900 snprintf(wl_key_index, sizeof(wl_key_index),"wl%s_key",index); 3901 }else 3902 snprintf(wl_key_index, sizeof(wl_key_index),"wl_key"); 3903 3904 snprintf(wl_key, sizeof(wl_key), "%s%s",wl_key_index, nvram_safe_get(wl_key_index)); 3905 if (!strlen(nvram_safe_get(wl_key))) { 3906 websBufferWrite(wp, "Invalid <b>%s</b>: must first specify a valid <b>Network Key %s</b><br>", 3907 v->longname, nvram_safe_get(wl_key_index)); 3908 if (nvram_match(name, "enabled")) { 3909 websBufferWrite(wp, "<b>%s</b> is <b>Disabled</b><br>", v->longname); 3910 nvram_set(name, "disabled"); 3911 } 3912 return; 3913 } 3914 } 3915 } 3916 else { 3917 if (!auth || !strcmp(auth, "shared") || ( auth_mode && !strcmp(auth_mode, "radius"))) { 3918 websBufferWrite(wp, "Invalid <b>WEP Encryption</b>: must be <b>Enabled</b> when <b>Network Authentication</b> is <b>%s</b><br>", auth_mode); 3919 return; 3920 } 3921 } 3922 3923 nvram_set(name, value); 3924 3925 ret_code = 0; 3926} 3927 3928static void 3929validate_wl_crypto(webs_t wp, char *value, struct variable *v, char *varname) 3930{ 3931 3932 assert(v); 3933 3934 ret_code = EINVAL; 3935 3936 if (!valid_choice(wp, value, v)){ 3937 websBufferWrite(wp, "Invalid crypto config string <b>%s</b>",value); 3938 return; 3939 } 3940 3941 if (varname) 3942 nvram_set(varname, value); 3943 else 3944 nvram_set(v->name, value); 3945 3946 ret_code = 0; 3947} 3948 3949#ifdef __CONFIG_NAT__ 3950static void 3951validate_wan_ifname(webs_t wp, char *value, struct variable *v, char *varname) 3952{ 3953 char ifname[64], *next=NULL; 3954 3955 assert(v); 3956 3957 ret_code = EINVAL; 3958 foreach (ifname, nvram_safe_get("wan_ifnames"), next) 3959 if (!strcmp(ifname, value)) { 3960 nvram_set(v->name, value); 3961 ret_code = 0; 3962 return; 3963 } 3964 websBufferWrite(wp, "Invalid <b>%s</b>: must be one of <b>%s</b><br>", v->longname, nvram_safe_get("wan_ifnames")); 3965} 3966#endif /* __CONFIG_NAT__ */ 3967 3968static void 3969validate_wl_afterburner(webs_t wp, char *value, struct variable *v, char *varname) 3970{ 3971 3972 assert(v); 3973 3974 ret_code = EINVAL; 3975 3976 if (!valid_choice(wp, value, v)){ 3977 websBufferWrite(wp, "Invalid afterburner config string <b>%s</b>",value); 3978 return; 3979 } 3980 3981 /* force certain wireless variables to fixed values */ 3982 if (!strcmp(value, "auto")) { 3983 if ( nvram_invmatch("wl_mode", "ap")) { 3984 /* notify the user */ 3985 websBufferWrite(wp, "Invalid <b>%s</b>: AfterBurner mode requires:" 3986 "<br><b>Mode</b> set to <b>Access Point</b>" 3987 "<br><b>Fragmentation value</b> set to <b>2346(disable fragmentation)</b>" 3988 "<br><b>AfterBurner mode is disabled!</b>" 3989 "<br>", v->longname); 3990 return; 3991 } 3992 } 3993 3994 if (varname) 3995 nvram_set(varname, value); 3996 else 3997 nvram_set(v->name, value); 3998 3999 ret_code = 0; 4000} 4001 4002static void 4003validate_wl_lazywds(webs_t wp, char *value, struct variable *v, char *varname) 4004{ 4005 assert(v); 4006 4007 ret_code = EINVAL; 4008 validate_choice(wp, value, v, varname); 4009} 4010 4011static void 4012validate_wl_wds_hwaddrs(webs_t wp, char *value, struct variable *v, char *varname) 4013{ 4014 assert(v); 4015 4016 ret_code = EINVAL; 4017 validate_list(wp, value, v, valid_hwaddr, varname); 4018} 4019 4020static void 4021validate_wl_mode(webs_t wp, char *value, struct variable *v, char *varname) 4022{ 4023 char *afterburner=NULL; 4024 4025 assert(v); 4026 4027 ret_code = EINVAL; 4028 4029 if (strcmp(value, "ap") && 4030 (afterburner = websGetVar(wp, "wl_afterburner", NULL)) && (!strcmp(afterburner, "auto"))) { 4031 websBufferWrite(wp, "Invalid <b>%s</b>: must be set to <b>Access Point</b> when AfterBurner is enabled.<br>", v->longname); 4032 return; 4033 } 4034 validate_choice(wp, value, v, varname); 4035} 4036 4037static void 4038validate_noack(webs_t wp, char *value, struct variable *v,char *varname) 4039{ 4040 char *wme=NULL; 4041 4042 assert(v); 4043 4044 ret_code = EINVAL; 4045 4046 /* return if wme is not enabled */ 4047 if (!(wme = websGetVar(wp, "wl_wme", NULL))){ 4048 ret_code = 0; 4049 return; 4050 }else if (strcmp(wme, "on")){ 4051 ret_code = 0; 4052 return; 4053 } 4054 4055 validate_choice(wp, value, v, varname); 4056} 4057 4058static void 4059validate_wl_wme_params(webs_t wp, char *value, struct variable *v,char *varname) 4060{ 4061 int n, i; 4062 int cwmin = 0, cwmax = 0; 4063 char *wme=NULL, *afterburner=NULL; 4064 char name[100]; 4065 char buf[1000] = "", *cur = buf; 4066 struct { 4067 char *name; 4068 int range; 4069 char *arg1; 4070 char *arg2; 4071 } field_attrib[] = { 4072 { "WME AC CWmin", 1, "0", "32767" }, 4073 { "WME AC CWmax", 1, "0", "32767" }, 4074 { "WME AC AIFSN", 1, "1", "15" }, 4075 { "WME AC TXOP(b)", 1, "0", "65504" }, 4076 { "WME AC TXOP(a/g)", 1, "0", "65504" }, 4077 { "WME AC Admin Forced", 0, "on", "off" } 4078 }; 4079 4080 assert(v); 4081 4082 ret_code = EINVAL; 4083 4084 /* return if wme is not enabled */ 4085 if (!(wme = websGetVar(wp, "wl_wme", NULL))){ 4086 ret_code =0; 4087 return; 4088 } else if (strcmp(wme, "on")){ 4089 ret_code = 0; 4090 return; 4091 } 4092 4093 /* return if afterburner enabled */ 4094 if ((afterburner = websGetVar(wp, "wl_afterburner", NULL)) && (!strcmp(afterburner, "auto"))){ 4095 ret_code =0; 4096 return; 4097 } 4098 4099 n = atoi(value) + 1; 4100 4101 for (i = 0; i < n; i++) { 4102 snprintf(name, sizeof(name), "%s%d", v->name, i); 4103 if (!(value = websGetVar(wp, name, NULL))){ 4104 ret_code = 0; 4105 return; 4106 } 4107 4108 if (!*value && v->nullok) 4109 continue; 4110 4111 if (i == 0) 4112 cwmin = atoi(value); 4113 else if (i == 1) { 4114 cwmax = atoi(value); 4115 if (cwmax < cwmin) { 4116 websBufferWrite(wp, "Invalid <b>%s</b> %d: greater than <b>%s</b> %d<br>", 4117 field_attrib[0].name, cwmin, field_attrib[i].name, cwmax); 4118 return; 4119 } 4120 } 4121 if (field_attrib[i].range) { 4122 if (atoi(value) < atoi(field_attrib[i].arg1) || atoi(value) > atoi(field_attrib[i].arg2)) { 4123 websBufferWrite(wp, "Invalid <b>%s</b> %d: should be in range %s to %s<br>", 4124 field_attrib[i].name, atoi(value), field_attrib[i].arg1, field_attrib[i].arg2); 4125 return; 4126 } 4127 } else { 4128 if (strcmp(value, field_attrib[i].arg1) && strcmp(value, field_attrib[i].arg2)) { 4129 websBufferWrite(wp, "Invalid <b>%s</b> %s: should be %s or %s<br>", 4130 field_attrib[i].name, value, field_attrib[i].arg1, field_attrib[i].arg2); 4131 } 4132 } 4133 4134 cur += snprintf(cur, buf + sizeof(buf) - cur, "%s%s", 4135 cur == buf ? "" : " ", value); 4136 } 4137 4138 if (varname) 4139 nvram_set(varname, buf); 4140 else 4141 nvram_set(v->name, buf); 4142 4143 ret_code = 0; 4144} 4145 4146/* Hook to write wl_* default set through to wl%d_* variable set */ 4147static void 4148wl_unit(webs_t wp, char *value, struct variable *v, char *varname) 4149{ 4150 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 4151 4152 assert(v); 4153 4154 ret_code = 0; 4155 4156 if (!value) return; 4157 4158 /* The unit numbers are built dynamically so what is 4159 present is assumed to be running */ 4160 4161 snprintf(prefix,sizeof(prefix),"wl%s_",value); 4162 4163 /* Write through to selected variable set */ 4164 for (; v >= variables && !strncmp(v->name, "wl_", 3); v--){ 4165 if ( v->ezc_flags & WEB_IGNORE) 4166 continue; 4167 nvram_set(strcat_r(prefix, &v->name[3], tmp), nvram_safe_get(v->name)); 4168 } 4169} 4170 4171#ifdef __CONFIG_NAT__ 4172static void 4173wan_primary(webs_t wp) 4174{ 4175 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 4176 int i; 4177 4178 for (i = 0; i < MAX_NVPARSE; i ++) { 4179 /* skip non-exist and disabled connection */ 4180 wan_prefix(i, prefix); 4181 if (!nvram_get(strcat_r(prefix, "unit", tmp))|| 4182 nvram_match(strcat_r(prefix, "proto", tmp), "disabled")) 4183 continue; 4184 /* make connection <i> primary */ 4185 nvram_set(strcat_r(prefix, "primary", tmp), "1"); 4186 /* notify the user */ 4187 websBufferWrite(wp, "<br><b>%s</b> is set to primary.", 4188 wan_name(i, prefix, tmp, sizeof(tmp))); 4189 break; 4190 } 4191} 4192 4193/* Hook to write wan_* default set through to wan%d_* variable set */ 4194static void 4195wan_unit(webs_t wp, char *value, struct variable *v, char *varname) 4196{ 4197 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 4198 char pppx[] = "pppXXXXXXXXXXX"; 4199 int unit, i; 4200 char *wan_ifname=NULL; 4201 int wan_disabled = 0; 4202 int wan_prim = 0; 4203 int wan_wildcard = 0; 4204 char *wan_pppoe_service=NULL; 4205 char *wan_pppoe_ac=NULL; 4206 char wan_tmp[NVRAM_BUFSIZE]; 4207 int wildcard; 4208 char *pppoe_service=NULL; 4209 char *pppoe_ac=NULL; 4210 char ea[ETHER_ADDR_LEN], wan_ea[ETHER_ADDR_LEN]; 4211 4212 assert(v); 4213 ret_code = 0; 4214 4215 /* Do not write through if no connections are present */ 4216 if ((unit = atoi(value)) < 0) 4217 return; 4218 4219 /* override wan_pppoe_ifname */ 4220 if (nvram_match("wan_proto", "pppoe")) { 4221 snprintf(pppx, sizeof(pppx), "ppp%d", unit); 4222 nvram_set("wan_pppoe_ifname", pppx); 4223 } 4224 4225 /* 4226 * Need to make sure this connection can co-exist with others. 4227 * Disable others if it can't (assuming this is the wanted one). 4228 * Disabled connection is for sure no problem to co-exist with 4229 * other connections. 4230 */ 4231 if (nvram_match("wan_proto", "disabled")) { 4232 /* Non primary always go with disabled connection. */ 4233 nvram_set("wan_primary", "0"); 4234 wan_disabled = 1; 4235 } 4236 /* 4237 * PPPoE connection is for sure no problem to co-exist with 4238 * other PPPoE connections even when they share the same 4239 * ethernet interface, but we need to make sure certain 4240 * PPPoE parameters are reasonablely different from eatch other 4241 * if they share the same ethernet interface. 4242 */ 4243 else if (nvram_match("wan_proto", "pppoe")) { 4244 /* must disable others if this connection is wildcard (any service any ac) */ 4245 wan_pppoe_service = nvram_get("wan_pppoe_service"); 4246 wan_pppoe_ac = nvram_get("wan_pppoe_ac"); 4247 wan_wildcard = (wan_pppoe_service == NULL || *wan_pppoe_service == 0) && 4248 (wan_pppoe_ac == NULL || *wan_pppoe_ac == 0); 4249 wan_ifname = nvram_safe_get("wan_ifname"); 4250 wan_name(unit, "wan_", wan_tmp, sizeof(wan_tmp)); 4251 /* check all PPPoE connections that share the same interface */ 4252 for (i = 0; i < MAX_NVPARSE; i ++) { 4253 /* skip the current connection */ 4254 if (i == unit) 4255 continue; 4256 /* skip non-exist and connection that does not share the same i/f */ 4257 wan_prefix(i, prefix); 4258 if (!nvram_get(strcat_r(prefix, "unit", tmp)) || 4259 nvram_match(strcat_r(prefix, "proto", tmp), "disabled") || 4260 nvram_invmatch(strcat_r(prefix, "ifname", tmp), wan_ifname)) 4261 continue; 4262 /* PPPoE can share the same i/f, but none can be wildcard */ 4263 if (nvram_match(strcat_r(prefix, "proto", tmp), "pppoe")) { 4264 if (wan_wildcard) { 4265 /* disable connection <i> */ 4266 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 4267 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 4268 /* notify the user */ 4269 websBufferWrite(wp, "<br><b>%s</b> is <b>disabled</b> because both " 4270 "<b>PPPoE Service Name</b> and <b>PPPoE Access Concentrator</b> " 4271 "in <b>%s</b> are empty.", 4272 wan_name(i, prefix, tmp, sizeof(tmp)), wan_tmp); 4273 } 4274 else { 4275 pppoe_service = nvram_get(strcat_r(prefix, "pppoe_service", tmp)); 4276 pppoe_ac = nvram_get(strcat_r(prefix, "pppoe_ac", tmp)); 4277 wildcard = (pppoe_service == NULL || *pppoe_service == 0) && 4278 (pppoe_ac == NULL || *pppoe_ac == 0); 4279 /* allow connection <i> if certain pppoe parameters are not all same */ 4280 if (!wildcard && 4281 (nvram_invmatch(strcat_r(prefix, "pppoe_service", tmp), nvram_safe_get("wan_pppoe_service")) || 4282 nvram_invmatch(strcat_r(prefix, "pppoe_ac", tmp), nvram_safe_get("wan_pppoe_ac")))) 4283 continue; 4284 /* disable connection <i> */ 4285 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 4286 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 4287 /* notify the user */ 4288 websBufferWrite(wp, "<br><b>%s</b> is <b>disabled</b> because both its " 4289 "<b>PPPoE Service Name</b> and <b>PPPoE Access Concentrator</b> " 4290 "are empty.", 4291 wan_name(i, prefix, tmp, sizeof(tmp))); 4292 } 4293 } 4294 /* other types can't (?) share the same i/f with PPPoE */ 4295 else { 4296 /* disable connection <i> */ 4297 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 4298 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 4299 /* notify the user */ 4300 websBufferWrite(wp, "<br><b>%s</b> is <b>disabled</b> because it can't " 4301 "share the same interface with <b>%s</b>.", 4302 wan_name(i, prefix, tmp, sizeof(tmp)), wan_tmp); 4303 } 4304 } 4305 } 4306 /* 4307 * All other types (now DHCP, Static) can't co-exist with 4308 * other connections if they use the same ethernet i/f. 4309 */ 4310 else { 4311 wan_ifname = nvram_safe_get("wan_ifname"); 4312 wan_name(unit, "wan_", wan_tmp, sizeof(wan_tmp)); 4313 /* check all connections that share the same interface */ 4314 for (i = 0; i < MAX_NVPARSE; i ++) { 4315 /* skip the current connection */ 4316 if (i == unit) 4317 continue; 4318 /* check if connection <i> exists and share the same i/f*/ 4319 wan_prefix(i, prefix); 4320 if (!nvram_get(strcat_r(prefix, "unit", tmp)) || 4321 nvram_match(strcat_r(prefix, "proto", tmp), "disabled") || 4322 nvram_invmatch(strcat_r(prefix, "ifname", tmp), wan_ifname)) 4323 continue; 4324 /* disable connection <i> */ 4325 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 4326 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 4327 /* notify the user */ 4328 websBufferWrite(wp, "<br><b>%s</b> is disabled because it can't share " 4329 "the ethernet interface with <b>%s</b>.", 4330 wan_name(i, prefix, tmp, sizeof(tmp)), wan_tmp); 4331 } 4332 } 4333 4334 /* 4335 * Check if MAC address has been changed. Need to sync it to all connections 4336 * that share the same i/f if it is changed. 4337 */ 4338 wan_prefix(unit, prefix); 4339 ether_atoe(nvram_safe_get("wan_hwaddr"), wan_ea); 4340 ether_atoe(nvram_safe_get(strcat_r(prefix, "hwaddr", tmp)), ea); 4341 if (memcmp(ea, wan_ea, ETHER_ADDR_LEN)) { 4342 wan_ifname = nvram_safe_get("wan_ifname"); 4343 wan_name(unit, "wan_", wan_tmp, sizeof(wan_tmp)); 4344 /* sync all connections that share the same interface */ 4345 for (i = 0; i < MAX_NVPARSE; i ++) { 4346 /* skip the current connection */ 4347 if (i == unit) 4348 continue; 4349 /* check if connection <i> exists and share the same i/f*/ 4350 wan_prefix(i, prefix); 4351 if (!nvram_get(strcat_r(prefix, "unit", tmp)) || 4352 nvram_invmatch(strcat_r(prefix, "ifname", tmp), wan_ifname)) 4353 continue; 4354 /* check if connection <i>'s hardware address is different */ 4355 if (ether_atoe(nvram_safe_get(strcat_r(prefix, "hwaddr", tmp)), ea) && 4356 !memcmp(ea, wan_ea, ETHER_ADDR_LEN)) 4357 continue; 4358 /* change connection <i>'s hardware address */ 4359 nvram_set(strcat_r(prefix, "hwaddr", tmp), nvram_safe_get("wan_hwaddr")); 4360 /* notify the user */ 4361 websBufferWrite(wp, "<br><b>MAC Address</b> in <b>%s</b> is changed to " 4362 "<b>%s</b> because it shares the ethernet interface with <b>%s</b>.", 4363 wan_name(i, prefix, tmp, sizeof(tmp)), nvram_safe_get("wan_hwaddr"), 4364 wan_tmp); 4365 } 4366 } 4367 4368 /* Set prefix */ 4369 wan_prefix(unit, prefix); 4370 4371 /* Write through to selected variable set */ 4372 for (; v >= variables && !strncmp(v->name, "wan_", 4); v--){ 4373 if (v->ezc_flags & WEB_IGNORE) 4374 continue; 4375 nvram_set(strcat_r(prefix, &v->name[4], tmp), nvram_safe_get(v->name)); 4376 } 4377 4378 /* 4379 * There must be one and only one primary connection among all 4380 * enabled connections so that traffic can be routed by default 4381 * through the primary connection unless they are targetted to 4382 * a specific connection by means of static routes. (Primary ~= 4383 * Default Gateway). 4384 */ 4385 /* the current connection is primary, set others to non-primary */ 4386 if (!wan_disabled && nvram_match(strcat_r(prefix, "primary", tmp), "1")) { 4387 /* set other connections to non-primary */ 4388 for (i = 0; i < MAX_NVPARSE; i ++) { 4389 /* skip the current connection */ 4390 if (i == unit) 4391 continue; 4392 /* skip non-exist and disabled connection */ 4393 wan_prefix(i, prefix); 4394 if (!nvram_get(strcat_r(prefix, "unit", tmp)) || 4395 nvram_match(strcat_r(prefix, "proto", tmp), "disabled")) 4396 continue; 4397 /* skip non-primary connection */ 4398 if (nvram_invmatch(strcat_r(prefix, "primary", tmp), "1")) 4399 continue; 4400 /* force primary to non-primary */ 4401 nvram_set(strcat_r(prefix, "primary", tmp), "0"); 4402 /* notify the user */ 4403 websBufferWrite(wp, "<br><b>%s</b> is set to non-primary.", 4404 wan_name(i, prefix, tmp, sizeof(tmp))); 4405 } 4406 wan_prim = 1; 4407 } 4408 /* the current connection is not parimary, check if there is any primary */ 4409 else { 4410 /* check other connections to see if there is any primary */ 4411 for (i = 0; i < MAX_NVPARSE; i ++) { 4412 /* skip the current connection */ 4413 if (i == unit) 4414 continue; 4415 /* primary connection exists, honor it */ 4416 wan_prefix(i, prefix); 4417 if (nvram_match(strcat_r(prefix, "primary", tmp), "1")) { 4418 wan_prim = 1; 4419 break; 4420 } 4421 } 4422 } 4423 /* no one is primary, pick the first enabled one as primary */ 4424 if (!wan_prim) 4425 wan_primary(wp); 4426} 4427#endif /* __CONFIG_NAT__ */ 4428 4429/* This is the monster V-block 4430 * 4431 * It controls the following functions 4432 * 4433 * Configuration variables are validated and saved in NVRAM 4434 * Variables saved by NVRAM save/restore routine 4435 * Method in which the variables are to be validates 4436 * SES handling 4437 * 4438 * The control flags: 4439 * EZC_FLAGS_READ,EZC_FLAGS_WRITE :Ses read/write flags 4440 * NVRAM_ENCRYPT: Encrypt variable prior to downloading NVRAM variable to file 4441 * NVRAM_MI: Multi instance NVRAM variable eg wlXX,wanXX 4442 * NVRAM_VLAN_MULTI: Special flag to handle oddball vlanXXname and its cousins 4443 * NVRAM_MP: Variable can be single & multi instance eg lan_ifname, lanX_ifname 4444 * NVRAM_IGNORE: Dont save/restore this var. 4445 * WEB_IGNORE: Don't validate or process this var during web validation. 4446 * 4447 * Below is the definition of the structure 4448 *struct variable { 4449 * char *name; <- name of variable 4450 * char *longname; <- display name 4451 * char *prefix; <- prefix for processing the multi-instance versions 4452 * void (*validate)(); <- Validation routine 4453 * char **argv; <- Optional argument vector for validation routine 4454 * int nullok; <- value can be NULL 4455 * int ezc_flags; <- control flags 4456 * }; 4457 * 4458 * IMPORTANT: 4459 * ========= 4460 * 4461 * The variables in tne table below determine if they will be saved/restored 4462 * by the UI NVRAM save/restore feature 4463 * 4464 * If an NVRAM variable is not present in this list it will 4465 * not be processed and thus will not be saved or restored. 4466 * 4467*/ 4468 4469/* 4470 * Variables are set in order (put dependent variables later). Set 4471 * nullok to TRUE to ignore zero-length values of the variable itself. 4472 * For more complicated validation that cannot be done in one pass or 4473 * depends on additional form components or can throw an error in a 4474 * unique painful way, write your own validation routine and assign it 4475 * to a hidden variable (e.g. filter_ip). 4476 * 4477 * EZC_FLAGS_READ : implies the variable will be returned for ezconfig read request 4478 * EZC_FLAGS_WRITE : allows the variable to be modified by the ezconfig tool 4479 * 4480 * The variables marked with EZConfig have to maintain backward compatibility. 4481 * If they cannot then the ezc_version has to be bumped up 4482 * 4483 */ 4484static char wl_prefix[]="wl"; 4485static char wan_prefix[]="wan"; 4486static char lan_prefix[]="lan"; 4487static char dhcp_prefix[]="dhcp"; 4488static char vlan_prefix[]="vlan"; 4489 4490static struct hsearch_data vtab; 4491 4492struct variable variables[] = { 4493 /* basic settings */ 4494 { "http_username", "Router Username",NULL, validate_name, ARGV("0", "63"), TRUE, EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4495 { "http_passwd", "Router Password",NULL, validate_name, ARGV("0", "63"), TRUE, NVRAM_ENCRYPT | EZC_FLAGS_WRITE }, 4496 { "http_wanport", "Router WAN Port",NULL, validate_range, ARGV("0", "65535"), TRUE, 0 }, 4497 { "http_lanport", "HTTP daemon lanport",NULL, NULL, NULL, TRUE, 0 }, 4498 { "router_disable", "Router Mode",NULL, validate_router_disable, ARGV("0", "1"), FALSE, 0 }, 4499 { "fw_disable", "Firewall",NULL, validate_choice, ARGV("0", "1"), FALSE, EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4500 { "time_zone", "Time Zone",NULL, validate_choice, ARGV("PST8PDT", "MST7MDT", "CST6CDT", "EST5EDT"), FALSE }, 4501 { "upnp_enable", "UPnP",NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 4502 { "ezc_enable", "EZConfig",NULL, validate_choice, ARGV("0", "1"), FALSE, EZC_FLAGS_READ | EZC_FLAGS_WRITE}, 4503 { "ntp_server", "NTP Servers",NULL, validate_ipaddrs, NULL, TRUE, 0 }, 4504 { "log_level", "Connection Logging",NULL, validate_range, ARGV("0", "3"), FALSE, 0 }, 4505 { "log_ipaddr", "Log LAN IP Address",NULL, validate_ipaddr, ARGV("lan_ipaddr", "lan_netmask"), TRUE, 0 }, 4506 { "log_ram_enable", "Syslog in RAM",NULL, validate_choice, ARGV("0", "1"), FALSE, 0 }, 4507 /* LAN settings */ 4508 { "lan_ifname" "LAN Interface Name", lan_prefix, NULL, NULL, FALSE, NVRAM_MI|NVRAM_IGNORE }, 4509 { "lan_dhcp", "DHCP Client", lan_prefix, validate_choice, ARGV("1", "0"), FALSE, NVRAM_MI | NVRAM_MP }, 4510 { "lan_ipaddr", "IP Address", lan_prefix, validate_lan_ipaddr, NULL, FALSE, NVRAM_MI| NVRAM_MP | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4511 { "lan_netmask", "Subnet Mask", lan_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 4512 { "lan_gateway", "Gateway Address", lan_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 4513 { "lan_proto", "DHCP Server", lan_prefix, validate_choice, ARGV("dhcp", "static"), FALSE, NVRAM_MI| NVRAM_MP | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4514 { "dhcp_start", "DHCP Server LAN IP Address Range", dhcp_prefix, validate_dhcp, NULL, FALSE, NVRAM_MI| NVRAM_MP | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4515 { "dhcp_end", "DHCP Server LAN IP End Address", dhcp_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 4516 { "dhcp_wins", "DHCP WINS domain", dhcp_prefix, NULL, NULL, TRUE, NVRAM_MI | NVRAM_MP}, 4517 { "dhcp_domain", "DHCP domain", dhcp_prefix, NULL, NULL, TRUE, NVRAM_MI | NVRAM_MP }, 4518 { "lan_lease", "DHCP Server Lease Time", lan_prefix, validate_range, ARGV("1", "604800"), FALSE, NVRAM_MI | NVRAM_MP |EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4519 { "lan_stp", "Spanning Tree Protocol", lan_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI | NVRAM_MP| EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4520 { "lan_route", "Static Routes", lan_prefix, validate_lan_route, NULL, FALSE, NVRAM_MI | NVRAM_MP }, 4521 { "lan_wins", "Lan WINS", lan_prefix, NULL, NULL, TRUE, NVRAM_MI| NVRAM_MP}, 4522 { "lan_domain", "Lan Domain", lan_prefix,NULL, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 4523 { "lan_route","LAN route", lan_prefix, NULL, NULL, TRUE, NVRAM_MI| NVRAM_MP }, 4524 { "lan_guest_ifname","Guest LAN 1", lan_prefix, validate_guest_lan_ifname, ARGV("1"), FALSE, NVRAM_MI| NVRAM_IGNORE}, 4525 /*VLAN config vars. These are multi-instance Used by NVRAM save/restore for the moment */ 4526 { "vlanhwname", "VLAN HW name", vlan_prefix, NULL, NULL, TRUE, NVRAM_VLAN_MULTI}, 4527 { "vlanports", "VLAN Ports", vlan_prefix, NULL, NULL, TRUE, NVRAM_VLAN_MULTI}, 4528#ifdef __CONFIG_NAT__ 4529 /* ALL wan_XXXX variables below till wan_unit variable are per-interface */ 4530 { "wan_desc", "Description", wan_prefix, validate_name, ARGV("0", "255"), TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4531 { "wan_proto", "Protocol", wan_prefix, validate_choice, ARGV("dhcp", "static", "pppoe", "disabled"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4532 { "wan_hostname", "Host Name", wan_prefix, validate_name, ARGV("0", "255"), TRUE, NVRAM_MI |EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4533 { "wan_domain", "Domain Name", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4534 { "wan_ifname", "Interface Name", wan_prefix, validate_wan_ifname, NULL, TRUE, NVRAM_MI }, 4535 { "wan_hwaddr", "MAC Address", wan_prefix, validate_hwaddr, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4536 { "wan_ipaddr", "IP Address", wan_prefix, validate_ipaddr, NULL, FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4537 { "wan_netmask", "Subnet Mask", wan_prefix, validate_ipaddr, NULL, FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4538 { "wan_gateway", "Default Gateway", wan_prefix, validate_ipaddr, NULL, TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4539 { "wan_dns", "DNS Servers", wan_prefix, validate_ipaddrs, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4540 { "wan_wins", "WINS Servers", wan_prefix, validate_ipaddrs, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4541 { "wan_pppoe_ifname", "PPPoE Interface Name", wan_prefix, NULL, NULL, TRUE, NVRAM_MI }, 4542 { "wan_pppoe_username", "PPPoE Username", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4543 { "wan_pppoe_passwd", "PPPoE Password", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_WRITE }, 4544 { "wan_pppoe_service", "PPPoE Service Name", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4545 { "wan_pppoe_ac", "PPPoE Access Concentrator", wan_prefix, validate_name, ARGV("0", "255"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4546 { "wan_pppoe_keepalive", "PPPoE Keep Alive", wan_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4547 { "wan_pppoe_demand", "PPPoE Connect on Demand", wan_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4548 { "wan_pppoe_idletime", "PPPoE Max Idle Time", wan_prefix, validate_range, ARGV("1", "3600"), TRUE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4549 { "wan_pppoe_mru", "PPPoE MRU", wan_prefix, validate_range, ARGV("128", "16384"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4550 { "wan_pppoe_mtu", "PPPoE MTU", wan_prefix, validate_range, ARGV("128", "16384"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4551 { "wan_primary", "Primary Interface", wan_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI }, 4552 { "wan_route", "Static Routes", wan_prefix, validate_wan_route, NULL, FALSE, NVRAM_MI }, 4553 /* MUST leave this entry here after all wl_XXXX per-interface variables */ 4554 { "wan_unit", "WAN Instance", wan_prefix, wan_unit, NULL, TRUE, NVRAM_MI|NVRAM_MP }, 4555 /* filter settings */ 4556 { "filter_macmode", "MAC Filter Mode", NULL, validate_choice, ARGV("disabled", "allow", "deny"), FALSE, 0 }, 4557 { "filter_maclist", "MAC Filter", NULL, validate_hwaddrs, NULL, TRUE, 0 }, 4558 { "filter_client", "LAN Client Filter", NULL, validate_filter_client, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 4559 /* routing settings */ 4560 { "forward_port", "Port Forward", NULL, validate_forward_port, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 4561 { "autofw_port", "Application Specific Port Forward", NULL, validate_autofw_port, ARGV("0", XSTR(MAX_NVPARSE - 1)), FALSE, NVRAM_GENERIC_MULTI }, 4562 { "dmz_ipaddr", "DMZ LAN IP Address", NULL, validate_ipaddr, ARGV("lan_ipaddr", "lan_netmask"), TRUE, 0 }, 4563#endif /* __CONFIG_NAT__ */ 4564 /* ALL wl_XXXX variables are per-interface */ 4565 { "wl_ssid", "Network Name (ESSID)", wl_prefix, validate_name, ARGV("1", "32"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4566 { "wl_guest_ssid_1", "Guest Network Name 1(SSID)", wl_prefix, validate_guest_ssid, ARGV("1"), FALSE, NVRAM_MI|NVRAM_IGNORE }, 4567 { "wl_guest_ssid_2", "Guest Network Name 2(SSID)", wl_prefix, validate_guest_ssid, ARGV("2"), FALSE, NVRAM_MI|NVRAM_IGNORE }, 4568 { "wl_guest_ssid_3", "Guest Network Name 3(SSID)", wl_prefix, validate_guest_ssid, ARGV("3"), FALSE, NVRAM_MI|NVRAM_IGNORE }, 4569 { "wl_guest_ssid_4", "Guest Network Name 4(SSID)", wl_prefix, validate_guest_ssid, ARGV("4"), FALSE, NVRAM_MI|NVRAM_IGNORE }, 4570 { "wl_ure", "URE Mode",NULL, validate_ure, ARGV("0"), FALSE, NVRAM_MI|NVRAM_IGNORE }, 4571 { "wl_closed", "Network Type", wl_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4572 { "wl_ap_isolate", "AP Isolate", wl_prefix, validate_choice, ARGV("0", "1"), FALSE,NVRAM_MI | 0 }, 4573 { "wl_country_code", "Country Code", wl_prefix, validate_country, NULL, FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4574 { "wl_mode", "Mode", wl_prefix, validate_wl_mode, ARGV("ap", "wds", "sta", "wet", "apsta"), FALSE,NVRAM_MI }, 4575 { "wl_infra", "Network", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 4576 { "wl_lazywds", "Bridge Restrict", wl_prefix, validate_wl_lazywds, ARGV("0", "1"), FALSE,NVRAM_MI }, 4577 { "wl_wds", "Bridges", wl_prefix, validate_wl_wds_hwaddrs, NULL, TRUE, NVRAM_MI }, 4578 { "wl_wds_timeout", "Link Timeout Interval", wl_prefix, NULL, NULL, TRUE, NVRAM_MI }, 4579 { "wl_macmode", "MAC Restrict Mode", wl_prefix, validate_choice, ARGV("disabled", "allow", "deny"), FALSE,NVRAM_MI }, 4580 { "wl_maclist", "Allowed MAC Address", wl_prefix, validate_hwaddrs, NULL, TRUE, NVRAM_MI }, 4581 { "wl_radio", "Radio Enable", wl_prefix, validate_choice, ARGV("0", "1"), FALSE, NVRAM_MI }, 4582 { "wl_phytype", "Radio Band", wl_prefix, validate_choice, ARGV("a", "b", "g"), TRUE, NVRAM_MI }, 4583 { "wl_antdiv", "Antenna Diversity", wl_prefix, validate_choice, ARGV("-1", "0", "1", "3"), FALSE, NVRAM_MI }, 4584 /* Channel and rate are fixed in wlconf() if incorrect */ 4585 { "wl_channel", "Channel", wl_prefix, validate_range, ARGV("0", "216"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4586 { "wl_reg_mode", "Regulatory Mode", wl_prefix, validate_choice, ARGV("off", "h", "d"), FALSE, NVRAM_MI }, 4587 { "wl_dfs_preism", "Pre-Network Radar Check", wl_prefix, validate_range, ARGV("0", "99"), FALSE,NVRAM_MI }, 4588 { "wl_dfs_postism", "In Network Radar Check", wl_prefix, validate_range, ARGV("10", "99"), FALSE,NVRAM_MI }, 4589 { "wl_tpc_db", "TPC Mitigation (db)", wl_prefix, validate_range, ARGV("0", "99"), FALSE,NVRAM_MI }, 4590 { "wl_rate", "Rate", wl_prefix, validate_range, ARGV("0", "54000000"), FALSE,NVRAM_MI }, 4591 { "wl_rateset", "Supported Rates", wl_prefix, validate_choice, ARGV("all", "default", "12"), FALSE,NVRAM_MI }, 4592 { "wl_mrate", "Multicast Rate", wl_prefix, validate_range, ARGV("0", "54000000"), FALSE,NVRAM_MI }, 4593 { "wl_frag", "Fragmentation Threshold", wl_prefix, validate_range, ARGV("256", "2346"), FALSE,NVRAM_MI }, 4594 { "wl_rts", "RTS Threshold", wl_prefix, validate_range, ARGV("0", "2347"), FALSE, NVRAM_MI }, 4595 { "wl_dtim", "DTIM Period", wl_prefix, validate_range, ARGV("1", "255"), FALSE, NVRAM_MI }, 4596 { "wl_bcn", "Beacon Interval", wl_prefix, validate_range, ARGV("1", "65535"), FALSE, NVRAM_MI }, 4597 { "wl_plcphdr", "Preamble Type", wl_prefix, validate_choice, ARGV("long", "short"), FALSE, NVRAM_MI }, 4598 { "wl_maxassoc", "Max Assocation Limit", wl_prefix, validate_range, ARGV("1", "256"), FALSE,NVRAM_MI }, 4599 { "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 | 0 }, 4600 { "wl_gmode_protection", "54g Protection", wl_prefix, validate_choice, ARGV("off", "auto"), FALSE,NVRAM_MI }, 4601 { "wl_frameburst", "XPress Technology", wl_prefix, validate_choice, ARGV("off", "on"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4602 { "wl_afterburner", "AfterBurner Technology", wl_prefix, validate_wl_afterburner, ARGV("off", "auto"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4603 { "wl_wme", "WME Support", wl_prefix, validate_choice, ARGV("off", "on"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4604 { "wl_wme_no_ack", "No-Acknowledgement", wl_prefix, validate_noack, ARGV("off", "on"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4605 { "wl_wme_ap_bk", "WME AP BK", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI }, 4606 { "wl_wme_ap_be", "WME AP BE", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI }, 4607 { "wl_wme_ap_vi", "WME AP VI", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI }, 4608 { "wl_wme_ap_vo", "WME AP VO", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI }, 4609 { "wl_wme_sta_bk", "WME STA BK", wl_prefix, validate_wl_wme_params, NULL, TRUE,NVRAM_MI }, 4610 { "wl_wme_sta_be", "WME STA BE", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI }, 4611 { "wl_wme_sta_vi", "WME STA VI", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI }, 4612 { "wl_wme_sta_vo", "WME STA VO", wl_prefix, validate_wl_wme_params, NULL, TRUE, NVRAM_MI }, 4613 /* security parameters */ 4614 { "wl_key", "Network Key Index", wl_prefix, validate_range, ARGV("1", "4"), FALSE,NVRAM_MI | EZC_FLAGS_WRITE }, 4615 { "wl_key1", "Network Key 1", wl_prefix, validate_wl_key, NULL, TRUE, NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 4616 { "wl_key2", "Network Key 2", wl_prefix, validate_wl_key, NULL, TRUE, NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 4617 { "wl_key3", "Network Key 3", wl_prefix, validate_wl_key, NULL, TRUE,NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 4618 { "wl_key4", "Network Key 4", wl_prefix, validate_wl_key, NULL, TRUE,NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 4619 { "wl_auth", "802.11 Authentication", wl_prefix, validate_wl_auth, ARGV("0", "1"), FALSE, NVRAM_MI | 0}, 4620 { "wl_auth_mode", "Network Authentication", wl_prefix, validate_wl_auth_mode, ARGV("radius", "none"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4621 { "wl_akm", "Authenticated Key Management", wl_prefix, validate_wl_akm, NULL, FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4622 { "wl_wep", "WEP Encryption", wl_prefix, validate_wl_wep, ARGV("disabled", "enabled"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4623 { "wl_crypto", "WPA Encryption", wl_prefix, validate_wl_crypto, ARGV("tkip", "aes", "tkip+aes"), FALSE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4624#ifdef BCMWPA2 4625 { "wl_net_reauth", "Network Re-auth Interval", wl_prefix, NULL, NULL, TRUE, NVRAM_MI }, 4626 { "wl_preauth", "Network Preauthentication Support", wl_prefix, validate_wl_preauth, ARGV("disabled", "enabled"), FALSE,NVRAM_MI | 0 }, 4627#endif 4628 { "wl_radius_ipaddr", "RADIUS Server", wl_prefix, validate_ipaddr, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4629 { "wl_radius_port", "RADIUS Port", wl_prefix, validate_range, ARGV("0", "65535"), FALSE,NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4630 { "wl_radius_key", "RADIUS Shared Secret", wl_prefix, validate_name, ARGV("0", "255"), TRUE, NVRAM_MI | NVRAM_ENCRYPT | EZC_FLAGS_WRITE}, 4631 { "wl_wpa_psk", "WPA Pre-Shared Key", wl_prefix, validate_wl_wpa_psk, ARGV("64"), TRUE, NVRAM_ENCRYPT | NVRAM_MI | EZC_FLAGS_WRITE}, 4632 { "wl_wpa_gtk_rekey", "Network Key Rotation Interval", wl_prefix, NULL, NULL, TRUE, NVRAM_MI | EZC_FLAGS_READ | EZC_FLAGS_WRITE }, 4633 /* Multi SSID Guest interface flag */ 4634 { "wl_guest", "Guest SSID Interface", wl_prefix, NULL, NULL, TRUE, WEB_IGNORE | NVRAM_MI }, 4635 /* MUST leave this entry here after all wl_XXXX variables */ 4636 { "wl_unit", "802.11 Instance", wl_prefix, wl_unit, NULL, TRUE, NVRAM_IGNORE | NVRAM_MI | NVRAM_MP }, 4637 /* Internal variables */ 4638 { "os_server", "OS Server", NULL, NULL, NULL, TRUE, 0 }, 4639 { "stats_server", "Stats Server", NULL, NULL, NULL, TRUE, 0 }, 4640 { "timer_interval", "Timer Interval", NULL, NULL, NULL, TRUE, 0 }, 4641 { "lan_ifname", "LAN Interface Name", lan_prefix, NULL, NULL, TRUE, NVRAM_MI | NVRAM_MP }, 4642 { "lan_ifnames", "LAN Interface Names", NULL, NULL, NULL, TRUE, 0 }, 4643 { "wan_ifnames", "WAN Interface Names", NULL, NULL, NULL, TRUE, 0 }, 4644}; 4645 4646/* build hashtable of the monster v-block 4647 4648 Inputs: 4649 -tab: hash table structure 4650 -vblock: the monster V-block 4651 -num_items: estimated size of hash table 4652 4653 Returns: 0 on success -1 on error 4654*/ 4655 4656int 4657hash_vtab(struct hsearch_data *tab,struct variable *vblock,int num_items) 4658{ 4659 ENTRY e, *ep=NULL; 4660 int count; 4661 4662 assert(tab); 4663 assert(vblock); 4664 4665 if (!num_items) return -1; 4666 4667 if (!hcreate_r(num_items,tab)) 4668 { 4669 return -1; 4670 } 4671 4672 4673 for (count=0; count < num_items; count++) 4674 { 4675 e.key = vblock[count].name; 4676 e.data = &vblock[count]; 4677 if (!hsearch_r(e, ENTER, &ep, tab)) 4678 return -1; 4679 } 4680 4681 return 0; 4682 4683} 4684/* The routine gets the pointer into the giant "V" block above give the cgi var name.. 4685 Inputs: 4686 -varname: Pointer to cgi var name 4687 4688 Returns: entry within "V" block or NULL if not found. 4689 4690 It will try the following forms 4691 varXX_type 4692 var_typeXX 4693 vlanXXtype 4694 4695 where XX is the instance number 4696 4697*/ 4698 4699static struct variable* 4700get_var_handle(char *varname) 4701{ 4702 ENTRY e, *ep=NULL; 4703 struct variable *variable=NULL; 4704 char *ptr=NULL,*ptr2=NULL; 4705 int offset; 4706 char prefix[8],tmp[64]; 4707 4708 if (!varname ) return NULL; 4709 if (!*varname) return NULL; 4710 4711 ep=NULL; 4712 e.key = varname; 4713 hsearch_r(e, FIND, &ep, &vtab); 4714 4715 4716 /* found something */ 4717 if (ep) 4718 { 4719 variable = (struct variable *)ep->data; 4720 if ( variable->ezc_flags & NVRAM_MP) return variable; 4721 4722 /* Drop the variable is multi instance but not 4723 Multi personality 4724 */ 4725 4726 if ( variable->ezc_flags & NVRAM_MI) return NULL; 4727 if ( variable->ezc_flags & NVRAM_VLAN_MULTI) return NULL; 4728 if ( variable->ezc_flags & NVRAM_GENERIC_MULTI) return NULL; 4729 4730 return variable; 4731 4732 } 4733 4734 /* variable not found could be the form of vlanXXtype, varXX_type or var_typeXX*/ 4735 4736 ptr=strchr(varname,'_'); 4737 4738 /* Is it vlanXXtype ? */ 4739 if (!ptr) 4740 { 4741 if (!strstr(varname,"vlan")) return NULL; 4742 strcpy(tmp,"vlan"); 4743 offset=4; 4744 ptr=&varname[offset]; 4745 while (*ptr){ 4746 if (!isdigit((int)*ptr)) tmp[offset++] = *ptr; 4747 ptr++; 4748 } 4749 4750 tmp[offset] = '\0'; 4751 ep = NULL; 4752 e.key = tmp; 4753 hsearch_r(e, FIND, &ep, &vtab); 4754 4755 /* check to see if this has the 4756 NVRAM_VLAN MULTI flag set in the v-block 4757 */ 4758 if (ep){ 4759 variable = (struct variable *)ep->data; 4760 if (variable->ezc_flags & NVRAM_VLAN_MULTI) 4761 return variable; 4762 } 4763 4764 return NULL; 4765 } 4766 4767 /* Is it varXX_type ? */ 4768 ptr2=varname; 4769 offset=0; 4770 memset(prefix,0,sizeof(prefix)); 4771 while (ptr2 < ptr){ 4772 if (isdigit((int)*ptr2)) break; 4773 prefix[offset++] =*ptr2; 4774 ptr2++; 4775 } 4776 snprintf(tmp,sizeof(tmp),"%s%s",prefix,ptr); 4777 4778 ep = NULL; 4779 e.key = tmp; 4780 hsearch_r(e, FIND, &ep, &vtab); 4781 4782 if (ep){ 4783 variable = (struct variable *)ep->data; 4784 if (variable->ezc_flags & NVRAM_MI) 4785 return variable; 4786 } 4787 4788 /* Is is a var_typeXX */ 4789 strncpy(tmp,varname,sizeof(tmp)); 4790 offset = strlen(varname) - 1 ; 4791 while(isdigit((int)tmp[offset])) 4792 tmp[offset--] = '\0'; 4793 ep = NULL; 4794 e.key = tmp; 4795 hsearch_r(e, FIND, &ep, &vtab); 4796 4797 if (ep){ 4798 variable = (struct variable *)ep->data; 4799 if (variable->ezc_flags & NVRAM_GENERIC_MULTI) 4800 return variable; 4801 } 4802 4803 return NULL; 4804} 4805int 4806variables_arraysize(void) 4807{ 4808 return ARRAYSIZE(variables); 4809} 4810 4811/* Need to do special handling for the lan cgi stuff as the DHCP ranges need 4812 overlap checking . In addition multi index variables are also present 4813 on the same page. This breaks the conventional validation flow as implemented 4814*/ 4815static void 4816validate_lan_cgi(webs_t wp) 4817{ 4818 char cgi_vars[][32]= { 4819 "lan_ifname", 4820 "lan_ifnames", 4821 "lan_dhcp", 4822 "lan_ipaddr", 4823 "lan_netmask", 4824 "lan_gateway", 4825 "lan_proto", 4826 "dhcp_start", 4827 "dhcp_end", 4828 "lan_lease", 4829 "lan_stp", 4830 "lan_route" 4831 }; 4832 4833 int count,num_ifaces; 4834 char *varname=NULL,*value=NULL; 4835 struct variable *v=NULL; 4836 int num_items = sizeof(cgi_vars)/sizeof(cgi_vars[0]); 4837 struct in_addr i_addr,g_addr,i_mask,g_mask; 4838 char err_msg[255] ; 4839 char vector[16]; 4840 int router_enable=0; 4841 4842 ret_code = EINVAL; 4843 4844 memset(err_msg,0,sizeof(err_msg)); 4845 memset(vector,0,sizeof(vector)); 4846 4847 websBufferInit(wp); 4848 if (!webs_buf) { 4849 snprintf(err_msg,sizeof(err_msg),"out of memory<br>"); 4850 goto validate_lan_cgi_error; 4851 } 4852 4853 value = websGetVar(wp, "num_lan_ifaces" , NULL); 4854 if (!value){ 4855 snprintf(err_msg,sizeof(err_msg), 4856 "unable to get number of lan interfaces<br>"); 4857 goto validate_lan_cgi_error; 4858 } 4859 4860 num_ifaces=atoi(value); 4861 4862 router_enable = nvram_match("router_disable","0"); 4863 4864 4865 /* Build a SSID valid enabled vector, skip processing if the 4866 vector is not set. Set vector on virtual i/f only if wl_vifs is set 4867 */ 4868 for (count=0; count < num_ifaces ; count++){ 4869 char buf[64]; 4870 4871 if (count) 4872 snprintf(buf,sizeof(buf),"lan%d_ifname",count); 4873 else 4874 snprintf(buf,sizeof(buf),"lan_ifname"); 4875 4876 value = websGetVar(wp, buf , NULL); 4877 if (value) 4878 { 4879 if (!*value) 4880 continue; 4881 4882 /* Clear lan mac address if the ip configuration is unset */ 4883 if (!strcmp(value,"NONE")){ 4884 /* Clear lanX_ifname if the inteface name has been set to NONE in the web page */ 4885 nvram_unset(buf); 4886 /* Clear up lanX_hwaddr */ 4887 snprintf(buf,sizeof(buf),"lan%d_hwaddr",count); 4888 nvram_unset(buf); 4889 continue; 4890 } 4891 4892 if (strstr(value,".")){ 4893 int unit=-1,subunit=-1; 4894 char *wl_vifs; 4895 4896 if (get_ifname_unit(value,&unit,&subunit) < 0) 4897 continue; 4898 if (subunit < 0 ) 4899 continue; 4900 4901 snprintf(buf,sizeof(buf),"wl%d_vifs",unit); 4902 4903 wl_vifs = nvram_get(buf); 4904 4905 if (!wl_vifs) 4906 continue; 4907 4908 if (!strstr(wl_vifs,value) ) 4909 continue; 4910 } 4911 4912 vector[count] = 1; 4913 } 4914 4915 } 4916 4917 /* check to see if the ip addresses overlap */ 4918 4919 for (count=0; count < num_ifaces ; count++){ 4920 int entry; 4921 char *valueA,*valueB; 4922 char lanA_ipaddr[32],lanA_netmask[32]; 4923 char lanB_ipaddr[32],lanB_netmask[32]; 4924 char dhcpA_start[32],dhcpB_start[32]; 4925 char dhcpA_end[32],dhcpB_end[32]; 4926 char lanA_ifname[32],lanB_ifname[32]; 4927 char lanA_proto[32],lanB_proto[32]; 4928 4929 /*Skip entry if the SSID is not turned on */ 4930 if (!vector[count]) 4931 continue; 4932 4933 if (count){ 4934 snprintf(lanA_ifname,sizeof(lanA_ifname),"lan%d_ifname",count); 4935 snprintf(lanA_ipaddr,sizeof(lanA_ipaddr),"lan%d_ipaddr",count); 4936 snprintf(lanA_netmask,sizeof(lanA_netmask),"lan%d_netmask",count); 4937 snprintf(lanA_proto,sizeof(lanA_proto),"lan%d_proto",count); 4938 snprintf(dhcpA_start,sizeof(dhcpA_start),"dhcp%d_start",count); 4939 snprintf(dhcpA_end,sizeof(dhcpA_end),"dhcp%d_end",count); 4940 }else{ 4941 snprintf(lanA_ifname,sizeof(lanA_ifname),"lan_ifname"); 4942 snprintf(lanA_ipaddr,sizeof(lanA_ipaddr),"lan_ipaddr"); 4943 snprintf(lanA_netmask,sizeof(lanA_netmask),"lan_netmask"); 4944 snprintf(lanA_proto,sizeof(lanA_proto),"lan_proto"); 4945 snprintf(dhcpA_start,sizeof(dhcpA_start),"dhcp_start"); 4946 snprintf(dhcpA_end,sizeof(dhcpA_end),"dhcp_end"); 4947 } 4948 4949 for (entry=0; entry < num_ifaces; entry++){ 4950 4951 if (count == entry) 4952 continue; 4953 4954 /*Skip entry if the SSID is not turned on */ 4955 if (!vector[entry]) 4956 continue; 4957 4958 if (entry){ 4959 snprintf(lanB_ifname,sizeof(lanB_ifname),"lan%d_ifname",entry); 4960 snprintf(lanB_ipaddr,sizeof(lanB_ipaddr),"lan%d_ipaddr",entry); 4961 snprintf(lanB_netmask,sizeof(lanB_netmask),"lan%d_netmask",entry); 4962 snprintf(lanB_proto,sizeof(lanB_proto),"lan%d_proto",count); 4963 snprintf(dhcpB_start,sizeof(dhcpB_start),"dhcp%d_start",entry); 4964 snprintf(dhcpB_end,sizeof(dhcpB_end),"dhcp%d_end",entry); 4965 }else{ 4966 snprintf(lanB_ifname,sizeof(lanB_ifname),"lan_ifname"); 4967 snprintf(lanB_ipaddr,sizeof(lanB_ipaddr),"lan_ipaddr"); 4968 snprintf(lanB_netmask,sizeof(lanB_netmask),"lan_netmask"); 4969 snprintf(lanB_proto,sizeof(lanB_proto),"lan_proto"); 4970 snprintf(dhcpB_start,sizeof(dhcpB_start),"dhcp_start"); 4971 snprintf(dhcpB_end,sizeof(dhcpB_end),"dhcp_end"); 4972 } 4973 4974 /* Check for the same interface unit numbers */ 4975 valueA = websGetVar(wp , lanA_ifname , NULL); 4976 valueB = websGetVar(wp , lanB_ifname , NULL); 4977 4978 if ((!valueA) ||(!valueB)) { 4979 snprintf(err_msg,sizeof(err_msg), 4980 "<br>%s is NULL<br>",(valueA) ? lanB_ifname : lanA_ifname); 4981 goto validate_lan_cgi_error; 4982 } 4983 4984 if (!strcmp(valueA,valueB)){ 4985 snprintf(err_msg,sizeof(err_msg), 4986 "<br>Interface %s selected more than once<br>",valueA); 4987 goto validate_lan_cgi_error; 4988 } 4989 4990 value = websGetVar(wp, lanA_ipaddr , NULL); 4991 if (! value ) goto validate_lan_cgi_error; 4992 (void)inet_aton(value,&i_addr); 4993 4994 value = websGetVar(wp, lanB_ipaddr , NULL); 4995 if (! value ) goto validate_lan_cgi_error; 4996 (void)inet_aton(value,&g_addr); 4997 4998 value = websGetVar(wp, lanA_netmask , NULL); 4999 if (! value ) goto validate_lan_cgi_error; 5000 (void)inet_aton(value,&i_mask); 5001 5002 value = websGetVar(wp, lanB_netmask , NULL); 5003 if (! value ) goto validate_lan_cgi_error; 5004 (void)inet_aton(value,&g_mask); 5005 5006 if ((i_addr.s_addr & i_mask.s_addr)==(g_addr.s_addr & g_mask.s_addr) ){ 5007 snprintf(err_msg,sizeof(err_msg), 5008 "<br>Overlapping IP address ranges:<br>(RangeA=%s/%s) (RangeB=%s/%s)<br>", 5009 lanA_ipaddr,lanA_netmask,lanB_ipaddr,lanB_netmask); 5010 goto validate_lan_cgi_error; 5011 } 5012 5013 valueA = websGetVar(wp , lanA_proto , NULL); 5014 valueB = websGetVar(wp , lanB_proto , NULL); 5015 5016 /* If any of the proto vars are null skip the check */ 5017 if ((!valueA) ||(!valueB)) 5018 continue; 5019 5020 /* Overlapping DHCP range check only if DHCP is the lan proto on both*/ 5021 if (!strcmp(valueA,"dhcp") && !strcmp(valueB,"dhcp")) 5022 { 5023 value = websGetVar(wp, dhcpA_start , NULL); 5024 if (! value ) goto validate_lan_cgi_error; 5025 (void) inet_aton(value,&i_addr); 5026 5027 value = websGetVar(wp, dhcpB_start , NULL); 5028 if (! value ) goto validate_lan_cgi_error; 5029 (void) inet_aton(value,&g_addr); 5030 5031 /* Are they in the same subnetwork ? */ 5032 5033 if ((i_addr.s_addr & i_mask.s_addr)==(g_addr.s_addr & g_mask.s_addr) ){ 5034 snprintf(err_msg,sizeof(err_msg), 5035 "<br>Overlapping DHCP start ranges<br>(RangeA=%s/%s) (RangeB=%s/%s)<br>", 5036 dhcpA_start,lanA_netmask,dhcpB_start,lanB_netmask); 5037 goto validate_lan_cgi_error; 5038 } 5039 5040 value = websGetVar(wp, dhcpA_end , NULL); 5041 if (! value ) goto validate_lan_cgi_error; 5042 (void) inet_aton(value,&i_addr); 5043 5044 value = websGetVar(wp, dhcpB_end , NULL); 5045 if (! value ) goto validate_lan_cgi_error; 5046 (void) inet_aton(value,&g_addr); 5047 5048 /* Are they in the same subnetwork ? */ 5049 5050 if ((i_addr.s_addr & i_mask.s_addr)==(g_addr.s_addr & g_mask.s_addr) ){ 5051 snprintf(err_msg,sizeof(err_msg), 5052 "<br>Overlapping DHCP end ranges<br>(RangeA=%s/%s) (RangeB=%s/%s)<br>", 5053 dhcpA_end,lanA_netmask,dhcpB_end,lanB_netmask); 5054 goto validate_lan_cgi_error; 5055 } 5056 } 5057 } 5058 } 5059 5060 ret_code = 0; 5061 5062 /* The individual validation functions will set ret_code to EINVAL 5063 if an error is encountered. On success zero is returned. 5064 Validation stops on the first error encountered 5065 */ 5066 for ( count = 0; ( count < num_items && !(ret_code) ); count++){ 5067 5068 char var[64]; 5069 int entry; 5070 5071 /* Lookup template */ 5072 varname = cgi_vars[count]; 5073 v = get_var_handle(varname); 5074 5075 /* Enumerate thru list of interfaces */ 5076 if (v) 5077 for (entry=0; entry < num_ifaces; entry++){ 5078 5079 /* Skip entry if the SSID is not turned on */ 5080 if (!vector[entry]) 5081 continue; 5082 5083 if (v->ezc_flags & WEB_IGNORE) 5084 continue; 5085 5086 if (entry && v->prefix ) 5087 snprintf(var,sizeof(var),"%s%d_%s", 5088 v->prefix,entry,&varname[strlen(v->prefix) + 1]); 5089 else 5090 snprintf(var,sizeof(var),"%s",varname); 5091 5092 value = websGetVar(wp, var, NULL); 5093 5094 if (value){ 5095 if ((!*value && v->nullok) || !v->validate) 5096 nvram_set(var, value); 5097 else 5098 v->validate(wp, value, v, var); 5099 } 5100 } 5101 5102 } 5103 5104 /* Set lanX_dhcp to static for all interfaces in router mode */ 5105 if (router_enable) 5106 for (count = 0; count < num_ifaces; count++){ 5107 char lan_dhcp[]="lanXXXXX_dhcp"; 5108 /* Skip entry if the SSID is not turned on */ 5109 if (!vector[count]) 5110 continue; 5111 if (count) 5112 snprintf(lan_dhcp,sizeof(lan_dhcp),"lan%d_dhcp",count); 5113 else 5114 snprintf(lan_dhcp,sizeof(lan_dhcp),"lan_dhcp"); 5115 nvram_set(lan_dhcp,"0"); 5116 5117 } 5118 5119 /* Handlers already print error messages. No need for further explanation */ 5120 if (ret_code) 5121 snprintf(err_msg,sizeof(err_msg),"Error during variable validation.<br>"); 5122 5123validate_lan_cgi_error: 5124 if (*err_msg) 5125 websWrite(wp, err_msg); 5126 5127 websBufferFlush(wp); 5128} 5129 5130static void 5131validate_cgi(webs_t wp) 5132{ 5133 struct variable *v=NULL; 5134 char *value=NULL; 5135 5136 websBufferInit(wp); 5137 if (!webs_buf) { 5138 websWrite(wp, "out of memory<br>"); 5139 websDone(wp, 0); 5140 return; 5141 } 5142 5143 5144 /* Validate and set variables in table order */ 5145 for (v = variables; v < &variables[ARRAYSIZE(variables)]; v++) { 5146 if (!(value = websGetVar(wp, v->name, NULL))) 5147 continue; 5148 5149 if (v->ezc_flags & WEB_IGNORE) 5150 continue; 5151 5152 if ((!*value && v->nullok) || !v->validate) 5153 nvram_set(v->name, value); 5154 else 5155 v->validate(wp, value, v, NULL); 5156 5157 } 5158 5159 websBufferFlush(wp); 5160} 5161 5162static int 5163apply_cgi(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 5164 char_t *url, char_t *path, char_t *query) 5165{ 5166 char *value=NULL; 5167 char *page=NULL; 5168 action = NOTHING; 5169 5170 websHeader(wp); 5171 websWrite(wp, (char_t *) apply_header); 5172 5173 page = websGetVar(wp, "page", ""); 5174 5175 value = websGetVar(wp, "action", ""); 5176 5177 /* Apply values */ 5178 if (!strcmp(value, "Apply")) { 5179 action = RESTART; 5180 websWrite(wp, "Validating values..."); 5181 5182 if (strcmp("lan.asp",page)) 5183 validate_cgi(wp); 5184 else 5185 validate_lan_cgi(wp); 5186 if(ret_code) 5187 { 5188 websWrite(wp, "<br>"); 5189 action = NOTHING; 5190 }else{ 5191 websWrite(wp, "done<br>"); 5192 websWrite(wp, "Committing values..."); 5193 nvram_set("is_modified", "1"); 5194 nvram_set("is_default", "0"); 5195 nvram_commit(); 5196 websWrite(wp, "done<br>"); 5197 } 5198 } 5199 5200 /* Restore defaults */ 5201 else if (!strncmp(value, "Restore", 7)) { 5202 websWrite(wp, "Restoring defaults..."); 5203 nvram_set("sdram_ncdl", "0"); 5204 nvram_set("restore_defaults", "1"); 5205 nvram_commit(); 5206 websWrite(wp, "done<br>"); 5207 action = REBOOT; 5208 } 5209 5210 /* Release lease */ 5211 else if (!strcmp(value, "Release")) { 5212 websWrite(wp, "Releasing lease..."); 5213 if (sys_release()) 5214 websWrite(wp, "error<br>"); 5215 else 5216 websWrite(wp, "done<br>"); 5217 action = NOTHING; 5218 } 5219 5220 /* Renew lease */ 5221 else if (!strcmp(value, "Renew")) { 5222 websWrite(wp, "Renewing lease..."); 5223 if (sys_renew()) 5224 websWrite(wp, "error<br>"); 5225 else 5226 websWrite(wp, "done<br>"); 5227 action = NOTHING; 5228 } 5229 5230 /* Reboot router */ 5231 else if (!strcmp(value, "Reboot")) { 5232 websWrite(wp, "Rebooting..."); 5233 action = REBOOT; 5234 } 5235 5236 /* Upgrade image */ 5237 else if (!strcmp(value, "Upgrade")) { 5238 char *os_name = nvram_safe_get("os_name"); 5239 char *os_server = websGetVar(wp, "os_server", nvram_safe_get("os_server")); 5240 char *os_version = websGetVar(wp, "os_version", "current"); 5241 char url[PATH_MAX]; 5242 if (!*os_version) 5243 os_version = "current"; 5244 snprintf(url, sizeof(url), "%s/%s/%s/%s.trx", 5245 os_server, os_name, os_version, os_name); 5246 websWrite(wp, "Retrieving %s...", url); 5247 if (sys_upgrade(url, NULL, NULL)) { 5248 websWrite(wp, "error<br>"); 5249 goto footer; 5250 } else { 5251 websWrite(wp, "done<br>"); 5252 action = REBOOT; 5253 } 5254 } 5255 5256 /* Report stats */ 5257 else if (!strcmp(value, "Stats")) { 5258 char *server = websGetVar(wp, "stats_server", nvram_safe_get("stats_server")); 5259 websWrite(wp, "Contacting %s...", server); 5260 if (sys_stats(server)) { 5261 websWrite(wp, "error<br>"); 5262 goto footer; 5263 } else { 5264 websWrite(wp, "done<br>"); 5265 nvram_set("stats_server", server); 5266 } 5267 } 5268 /* Radio On Off */ 5269 else if (!strcmp(value, "RadioOff")) { 5270 websWrite(wp, "Turing Off Radio..."); 5271 wl_radio_onoff(wp, 1); 5272 action = NOTHING; 5273 } 5274 else if (!strcmp(value, "RadioOn")) { 5275 websWrite(wp, "Radio on..."); 5276 wl_radio_onoff(wp, 0); 5277 action = NOTHING; 5278 } 5279#ifdef __CONFIG_NAT__ 5280 /* Delete connection */ 5281 else if (!strcmp(value, "Delete")) { 5282 int unit; 5283 if (!(value = websGetVar(wp, "wan_unit", NULL)) || 5284 (unit = atoi(value)) < 0 || unit >= MAX_NVPARSE) { 5285 websWrite(wp, "Unable to delete connection, index error."); 5286 action = NOTHING; 5287 } 5288 else { 5289 struct nvram_tuple *t; 5290 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 5291 int unit2, units = 0; 5292 /* 5293 * We can't delete the last connection since we can't differentiate 5294 * the cases where user does not want any connection (user deletes 5295 * the last one) vs. the router is booted the first time when there 5296 * is no connection at all (where a default one is created anyway). 5297 */ 5298 for (unit2 = 0; unit2 < MAX_NVPARSE; unit2 ++) { 5299 wan_prefix(unit2, prefix); 5300 if (nvram_get(strcat_r(prefix, "unit", tmp)) && units++ > 0) 5301 break; 5302 } 5303 if (units < 2) { 5304 websWrite(wp, "Can not delete the last connection."); 5305 action = NOTHING; 5306 } 5307 else { 5308 /* set prefix */ 5309 wan_prefix(unit, prefix); 5310 /* remove selected wan%d_ set */ 5311 websWrite(wp, "Deleting connection..."); 5312 for (t = router_defaults; t->name; t ++) { 5313 if (!strncmp(t->name, "wan_", 4)) 5314 nvram_unset(strcat_r(prefix, &t->name[4], tmp)); 5315 } 5316 /* fix unit number */ 5317 unit2 = unit; 5318 for (; unit < MAX_NVPARSE; unit ++) { 5319 wan_prefix(unit, prefix); 5320 if (nvram_get(strcat_r(prefix, "unit", tmp))) 5321 break; 5322 } 5323 if (unit >= MAX_NVPARSE) { 5324 unit = unit2 - 1; 5325 for (; unit >= 0; unit --) { 5326 wan_prefix(unit, prefix); 5327 if (nvram_get(strcat_r(prefix, "unit", tmp))) 5328 break; 5329 } 5330 } 5331 snprintf(tmp, sizeof(tmp), "%d", unit); 5332 nvram_set("wan_unit", tmp); 5333 /* check if there is any primary connection - see comment in wan_unit() */ 5334 for (unit = 0; unit < MAX_NVPARSE; unit ++) { 5335 wan_prefix(unit, prefix); 5336 if (!nvram_get(strcat_r(prefix, "unit", tmp))) 5337 continue; 5338 if (nvram_invmatch(strcat_r(prefix, "proto", tmp), "disabled") && 5339 nvram_match(strcat_r(prefix, "primary", tmp), "1")) 5340 break; 5341 } 5342 /* no one is primary, pick the first enabled one as primary */ 5343 if (unit >= MAX_NVPARSE) 5344 wan_primary(wp); 5345 /* save the change */ 5346 nvram_set("is_modified", "1"); 5347 nvram_set("is_default", "0"); 5348 nvram_commit(); 5349 websWrite(wp, "done<br>"); 5350 action = RESTART; 5351 } 5352 } 5353 } 5354#endif /* __CONFIG_NAT__ */ 5355 5356 /* Invalid action */ 5357 else 5358 websWrite(wp, "Invalid action %s<br>", value); 5359 5360 footer: 5361 websWrite(wp, (char_t *) apply_footer, websGetVar(wp, "page", "")); 5362 websFooter(wp); 5363 websDone(wp, 200); 5364 5365 if (action == RESTART) 5366 sys_restart(); 5367 else if (action == REBOOT) 5368 sys_reboot(); 5369 5370 return 1; 5371} 5372 5373/* Copy all wl%d_XXXXX to wl_XXXXX */ 5374static int 5375copy_wl_index_to_unindex(webs_t wp, char_t *urlPrefix, char_t *webDir, 5376 int arg, char_t *url, char_t *path, char_t *query) 5377{ 5378 struct variable *v=NULL; 5379 char *value=NULL; 5380 char name[IFNAMSIZ], os_name[IFNAMSIZ], *next=NULL; 5381 int unit = 0; 5382 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 5383 char unit_str[]={'\0','\0','\0','\0','\0'}; 5384 int applying = 0; 5385 5386 /* Can enter this function through GET or POST */ 5387 if ((value = websGetVar(wp, "action", NULL))) { 5388 if (strcmp(value, "Select")) 5389 { 5390 /* we need to make sure wl_unit on the web page matches the 5391 wl_unit in NVRAM. If they match, bail out now, otherwise 5392 proceed with the rest of the function */ 5393 5394 if ((value = websGetVar(wp, "wl_unit", NULL))) { 5395 if (!strcmp( nvram_safe_get("wl_unit" ), value)) 5396 return apply_cgi(wp, urlPrefix, webDir, arg, url, path, query); 5397 } 5398 applying = 1; 5399 } 5400 } 5401 5402 /* copy wl%d_XXXXXXXX to wl_XXXXXXXX */ 5403 if ((value = websGetVar(wp, "wl_unit", NULL))) { 5404 strncpy(unit_str,value,sizeof(unit_str)); 5405 } else { 5406 char ifnames[256]; 5407 snprintf(ifnames, sizeof(ifnames), "%s %s %s", 5408 nvram_safe_get("lan_ifnames"), 5409 nvram_safe_get("wan_ifnames"), 5410 nvram_safe_get("unbridged_ifnames")); 5411 5412 if (!remove_dups(ifnames,sizeof(ifnames))){ 5413 websError(wp, 400, "Unable to remove duplicate interfaces from ifname list<br>"); 5414 return -1; 5415 } 5416 5417 /* Probe for first wl interface */ 5418 foreach(name, ifnames, next) { 5419 if (nvifname_to_osifname( name, os_name, sizeof(os_name) ) < 0) 5420 continue; 5421 if (wl_probe(os_name) == 0 && 5422 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit)) == 0){ 5423 snprintf(unit_str,sizeof(unit_str),"%d",unit); 5424 break; 5425 } 5426 } 5427 5428 } 5429 if (*unit_str) { 5430 snprintf(prefix, sizeof(prefix), "wl%s_", unit_str); 5431 for (v = variables; v < &variables[ARRAYSIZE(variables)]; v++) { 5432 if (v->ezc_flags & WEB_IGNORE) 5433 continue; 5434 if (!strncmp(v->name, "wl_", 3)) 5435 nvram_set(v->name, nvram_safe_get(strcat_r(prefix, &v->name[3], tmp))); 5436 if (!strncmp(v->name, "wl_unit", 7)) 5437 break; 5438 } 5439 } 5440 5441 /* Set currently selected unit */ 5442 nvram_set("wl_unit", unit_str); 5443 5444 if( applying ) 5445 return apply_cgi(wp, urlPrefix, webDir, arg, url, path, query); 5446 5447 /* Display the page */ 5448 return websDefaultHandler(wp, urlPrefix, webDir, arg, url, path, query); 5449} 5450 5451 5452#ifdef __CONFIG_NAT__ 5453static int 5454wan_asp(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, 5455 char_t *url, char_t *path, char_t *query) 5456{ 5457 struct variable *v=NULL; 5458 char *value=NULL; 5459 int unit = 0; 5460 char tmp[NVRAM_BUFSIZE], prefix[] = "wanXXXXXXXXXX_"; 5461 char ustr[16]; 5462 struct nvram_tuple *t=NULL; 5463 5464 /* Can enter this function through GET or POST */ 5465 if ((value = websGetVar(wp, "action", NULL))) { 5466 if (!strcmp(value, "New")) { 5467 /* pick one that 'does not' exist */ 5468 for (unit = 0; unit < MAX_NVPARSE; unit ++) { 5469 wan_prefix(unit, prefix); 5470 if (!nvram_get(strcat_r(prefix, "unit", tmp))) 5471 break; 5472 } 5473 if (unit >= MAX_NVPARSE) { 5474 websHeader(wp); 5475 websWrite(wp, (char_t *) apply_header); 5476 websWrite(wp, "Unable to create new connection. Maximum %d.", MAX_NVPARSE); 5477 websWrite(wp, (char_t *) apply_footer, websGetVar(wp, "page", "")); 5478 websFooter(wp); 5479 websDone(wp, 200); 5480 return 1; 5481 } 5482 /* copy default to newly created wan%d_ set */ 5483 for (t = router_defaults; t->name; t ++) { 5484 if (!strncmp(t->name, "wan_", 4)) 5485 nvram_set(strcat_r(prefix, &t->name[4], tmp), t->value); 5486 } 5487 /* the following variables must be overwritten */ 5488 snprintf(ustr, sizeof(ustr), "%d", unit); 5489 nvram_set(strcat_r(prefix, "unit", tmp), ustr); 5490 nvram_set(strcat_r(prefix, "proto", tmp), "disabled"); 5491 nvram_set(strcat_r(prefix, "ifname", tmp), nvram_safe_get("wan_ifname")); 5492 nvram_set(strcat_r(prefix, "hwaddr", tmp), nvram_safe_get("wan_hwaddr")); 5493 nvram_set(strcat_r(prefix, "ifnames", tmp), nvram_safe_get("wan_ifnames")); 5494 /* commit change */ 5495 nvram_set("is_modified", "1"); 5496 nvram_set("is_default", "0"); 5497 nvram_commit(); 5498 } 5499 else if (!strcmp(value, "Select")) { 5500 if ((value = websGetVar(wp, "wan_unit", NULL))) 5501 unit = atoi(value); 5502 else 5503 unit = -1; 5504 } 5505 else 5506 return apply_cgi(wp, urlPrefix, webDir, arg, url, path, query); 5507 } 5508 else if ((value = websGetVar(wp, "wan_unit", NULL))) 5509 unit = atoi(value); 5510 else 5511 unit = atoi(nvram_safe_get("wan_unit")); 5512 if (unit < 0 || unit >= MAX_NVPARSE) 5513 unit = 0; 5514 5515 /* Set prefix */ 5516 wan_prefix(unit, prefix); 5517 5518 /* copy wan%d_ set to wan_ set */ 5519 for (v = variables; v < &variables[ARRAYSIZE(variables)]; v++) { 5520 if (v->ezc_flags & WEB_IGNORE) 5521 continue; 5522 if (strncmp(v->name, "wan_", 4)) 5523 continue; 5524 value = nvram_get(strcat_r(prefix, &v->name[4], tmp)); 5525 if (value) 5526 nvram_set(v->name, value); 5527 if (!strncmp(v->name, "wan_unit", 8)) 5528 break; 5529 } 5530 5531 /* Set currently selected unit */ 5532 snprintf(tmp, sizeof(tmp), "%d", unit); 5533 nvram_set("wan_unit", tmp); 5534 5535 /* Display the page */ 5536 return websDefaultHandler(wp, urlPrefix, webDir, arg, url, path, query); 5537} 5538#endif /* __CONFIG_NAT__ */ 5539 5540#ifdef WEBS 5541 5542void 5543initHandlers(void) 5544{ 5545 websAspDefine("nvram_get", ej_nvram_get); 5546 websAspDefine("nvram_match", ej_nvram_match); 5547 websAspDefine("nvram_invmatch", ej_nvram_invmatch); 5548 websAspDefine("nvram_list", ej_nvram_list); 5549 websAspDefine("filter_client", ej_filter_client); 5550 websAspDefine("forward_port", ej_forward_port); 5551 websAspDefine("static_route", ej_static_route); 5552 websAspDefine("localtime", ej_localtime); 5553 websAspDefine("dumplog", ej_dumplog); 5554 websAspDefine("syslog", ej_syslog); 5555 websAspDefine("dumpleases", ej_dumpleases); 5556 websAspDefine("link", ej_link); 5557 websAspDefine("wme_match_op", ej_wme_match_op); 5558 5559 websUrlHandlerDefine("/apply.cgi", NULL, 0, apply_cgi, 0); 5560 websUrlHandlerDefine("/wireless.asp", NULL, 0, copy_wl_index_to_unindex, 0); 5561 5562 websSetPassword(nvram_safe_get("http_passwd")); 5563 5564 websSetRealm("Broadcom Home Gateway Reference Design"); 5565 5566 /* Initialize hash table */ 5567 hash_vtab(&vtab,v,variables_arraysize()); 5568} 5569 5570#else /* !WEBS */ 5571 5572int internal_init(void) 5573{ 5574 /* Initialize hash table */ 5575 if (hash_vtab(&vtab,variables,variables_arraysize())) 5576 return -1; 5577 return 0; 5578} 5579static void 5580do_auth(char *userid, char *passwd, char *realm) 5581{ 5582 assert(userid); 5583 assert(passwd); 5584 assert(realm); 5585 5586 strncpy(userid, nvram_safe_get("http_username"), AUTH_MAX); 5587 strncpy(passwd, nvram_safe_get("http_passwd"), AUTH_MAX); 5588 strncpy(realm, "Broadcom Home Gateway Reference Design", AUTH_MAX); 5589} 5590 5591char post_buf[POST_BUF_SIZE]; 5592char ezc_version[128]; 5593char no_cache[] = 5594"Cache-Control: no-cache\r\n" 5595"Pragma: no-cache\r\n" 5596"Expires: 0" 5597; 5598 5599char download_hdr[] = 5600"Cache-Control: no-cache\r\n" 5601"Pragma: no-cache\r\n" 5602"Expires: 0\r\n" 5603"Content-Type: application/download\r\n" 5604"Content-Disposition: attachment ; filename=nvram.txt" 5605; 5606 5607static void 5608do_apply_post(char *url, FILE *stream, int len, char *boundary) 5609{ 5610 assert(url); 5611 assert(stream); 5612 5613 /* Get query */ 5614 if (!fgets(post_buf, MIN(len + 1, sizeof(post_buf)), stream)) 5615 return; 5616 len -= strlen(post_buf); 5617 5618 /* Initialize CGI */ 5619 init_cgi(post_buf); 5620 5621 /* Slurp anything remaining in the request */ 5622 while (len--) 5623 (void) fgetc(stream); 5624} 5625 5626static void 5627do_apply_cgi(char *url, FILE *stream) 5628{ 5629 char *path=NULL, *query=NULL; 5630 5631 assert(url); 5632 assert(stream); 5633 5634 /* Parse path */ 5635 query = url; 5636 path = strsep(&query, "?") ? : url; 5637 5638 apply_cgi(stream, NULL, NULL, 0, url, path, query); 5639 5640 /* Reset CGI */ 5641 init_cgi(NULL); 5642} 5643 5644 5645static void 5646do_upgrade_post(char *url, FILE *stream, int len, char *boundary) 5647{ 5648 char buf[1024]; 5649 5650 assert(url); 5651 assert(stream); 5652 5653 ret_code = EINVAL; 5654 5655 /* Look for our part */ 5656 while (len > 0) { 5657 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 5658 return; 5659 len -= strlen(buf); 5660 if (!strncasecmp(buf, "Content-Disposition:", 20) && 5661 strstr(buf, "name=\"file\"")) 5662 break; 5663 } 5664 5665 /* Skip boundary and headers */ 5666 while (len > 0) { 5667 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 5668 return; 5669 len -= strlen(buf); 5670 if (!strcmp(buf, "\n") || !strcmp(buf, "\r\n")) 5671 break; 5672 } 5673 5674 ret_code = sys_upgrade(NULL, stream, &len); 5675 5676 /* Slurp anything remaining in the request */ 5677 while (len--) 5678 (void) fgetc(stream); 5679} 5680 5681static void 5682do_upgrade_cgi(char *url, FILE *stream) 5683{ 5684 assert(url); 5685 assert(stream); 5686 5687 websHeader(stream); 5688 websWrite(stream, (char_t *) apply_header); 5689 5690 /* We could probably be more informative here... */ 5691 if (ret_code) 5692 websWrite(stream, "Error during upgrade<br>"); 5693 else 5694 websWrite(stream, "Upgrade complete. Rebooting...<br>"); 5695 5696 websWrite(stream, (char_t *) apply_footer, "firmware.asp"); 5697 websFooter(stream); 5698 websDone(stream, 200); 5699 5700 /* Reboot if successful */ 5701 if (ret_code == 0) 5702 sys_reboot(); 5703} 5704/* Utility function to remove duplicate entries in a space separated list 5705 */ 5706 5707static char * 5708remove_dups(char *inlist, int inlist_size) 5709{ 5710 char name[IFNAMSIZ], *next=NULL; 5711 char *outlist; 5712 5713 if (!inlist_size) 5714 return NULL; 5715 5716 if (!inlist) 5717 return NULL; 5718 5719 outlist =(char *) malloc(inlist_size); 5720 5721 if (!outlist ) return NULL; 5722 5723 memset(outlist,0,inlist_size); 5724 5725 foreach(name,inlist,next) 5726 { 5727 if (strstr(outlist,name) == NULL) 5728 { 5729 if( strlen(outlist) == 0 ) 5730 { 5731 snprintf(outlist,inlist_size,"%s", name); 5732 } 5733 else 5734 { 5735 strncat( outlist, " ", inlist_size - strlen(outlist) ); 5736 strncat( outlist, name, inlist_size - strlen(outlist) ); 5737 } 5738 } 5739 } 5740 5741 strncpy(inlist,outlist,inlist_size); 5742 5743 free(outlist); 5744 return inlist; 5745 5746} 5747/* This utility routine builds the wl prefixes from wl_unit. 5748 * Input is expected to be a null terminated string 5749 * 5750 * Inputs -prefix: Pointer to prefix buffer 5751 * -prefix_size: Size of buffer 5752 * -Mode flag: If set generates unit.subunit output 5753 * if not set generates unit only 5754 * -ifname: Optional interface name string 5755 * 5756 * 5757 * Returns - pointer to prefix, NULL if error. 5758 * 5759 * 5760*/ 5761static char * 5762make_wl_prefix(char *prefix,int prefix_size, int mode, char *ifname) 5763{ 5764 int unit=-1,subunit=-1; 5765 char *wl_unit=NULL; 5766 5767 assert(prefix); 5768 assert(prefix_size); 5769 5770 if (ifname){ 5771 assert(*ifname); 5772 wl_unit=ifname; 5773 }else{ 5774 wl_unit=nvram_get("wl_unit"); 5775 5776 if (!wl_unit) 5777 return NULL; 5778 } 5779 5780 if (get_ifname_unit(wl_unit,&unit,&subunit) < 0 ) 5781 return NULL; 5782 5783 if (unit < 0) return NULL; 5784 5785 if ((mode) && (subunit > 0 )) 5786 snprintf(prefix, prefix_size, "wl%d.%d_", unit,subunit); 5787 else 5788 snprintf(prefix, prefix_size, "wl%d_", unit); 5789 5790 return prefix; 5791} 5792 5793/* Format of the NVRAM text file is as follows 5794 * the following major sections 5795 * Header Block 5796 * Constraint Block 5797 * NVRAM variables 5798 * 5799 * Header consists of : 5800 * LineCount 5801 * Checksum 5802 * 5803 * Constraint block consists of : 5804 * Defined by NVRAM_CONSTRAINT_VARS 5805 * 5806 * 5807*/ 5808 5809/* Get major os version. The nvram variable gives the whole thing. 5810 * this function avoids the messy parsing. 5811 * Used by NVRAM constraint validation routines. 5812 * The input argument is not used. This is used to maintain 5813 * argument list compatability with nvram_get(). 5814 * 5815*/ 5816static char* 5817osversion_get(const char *name) 5818{ 5819 5820 static char ret_string[32]; 5821 5822 assert(name); 5823 5824 snprintf(ret_string,sizeof(ret_string),"%d.%d", 5825 EPI_MAJOR_VERSION,EPI_MINOR_VERSION); 5826 5827 5828 return ret_string; 5829 5830} 5831 5832/* This routine strips the CRLF from the HTTP stream */ 5833/* Returns new length or -1 if there is an error*/ 5834static int 5835remove_crlf(char *buf, int len) 5836{ 5837 5838 int slen; 5839 if (!buf) return -1; 5840 if (!len) return 0; 5841 5842 slen = strlen(buf); 5843 len = len-slen; 5844 if ((buf[slen-1] == '\n' ) && (buf[slen-2] == '\r' )){ 5845 buf[slen-1]='\0'; 5846 buf[slen-2]='\0'; 5847 5848 } 5849 else if ( buf[slen-1] == '\n' ) buf[slen-1]='\0'; 5850 5851 return len; 5852} 5853/* Utility routine to add a string from a string buffer. 5854 * 5855 * Routine expects that the buffer is composed of text strings with 5856 * a null as the delimiter. 5857 * 5858 * Input is expected to be a null terminated string 5859 * 5860 * Inputs -Pointer to char buffer 5861 * -NULL input terminated string 5862 * -Offset to end of used area. Including the NULL terminator 5863 * -Size of the buffer (to avoid running of the end of the buffer) 5864 * 5865 * 5866 * Returns - Number of bytes occupied including NULL terminator. -1 if error 5867 * 5868 * 5869*/ 5870static int 5871add_string(char *buf, char *string, int start, int bufsize) 5872{ 5873 int len; 5874 5875 assert(buf); 5876 5877 if (!string) return -1; 5878 if (!*string) return -1; 5879 if (!bufsize) return -1; 5880 if (start >=bufsize) return -1; 5881 5882 len = strlen(string); 5883 5884 if ( (start + len + 1) >= bufsize ) return -1; 5885 5886 strncpy(buf,string,len); 5887 5888 return start + len + 1; 5889} 5890static void 5891do_nvramul_post(char *url, FILE *stream, int len, char *boundary) 5892{ 5893 char buf[1024]; 5894 int index,cur_entry; 5895 char *ptr=NULL; 5896 char *name=NULL; 5897 char tmp[NVRAM_MAX_STRINGSIZE]; 5898 char file_checksum[NVRAM_SHA1BUFSIZE],checksum[NVRAM_SHA1BUFSIZE]; 5899 char key[NVRAM_FILEKEYSIZE]; 5900 int checksum_linenum = NVRAM_CHECKSUM_LINENUM; 5901 char salt[NVRAM_SALTSIZE]; 5902 int numlines=0; 5903 int entries,offset,slen; 5904 char passphrase[]=NVRAM_PASSPHRASE; 5905 char nvram_file_header[][NVRAM_MAX_STRINGSIZE/2] = NVRAM_FILEHEADER; 5906 upload_constraints constraint_vars [] = NVRAM_CONSTRAINT_VARS; 5907 struct pb { 5908 char header[NVRAM_HEADER_LINECOUNT(nvram_file_header)][NVRAM_MAX_STRINGSIZE]; 5909 char buf[NVRAM_SPACE]; 5910 }*tmpbuf=NULL; 5911 5912 assert(stream); 5913 5914 entries = NVRAM_HEADER_LINECOUNT(nvram_file_header); 5915 ret_code = EINVAL; 5916 5917 /* Look for our part */ 5918 while (len > 0) { 5919 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 5920 return; 5921 5922 /* Remove LF that fgets()drags in */ 5923 len=remove_crlf(buf,len); 5924 /* look for start of attached file header */ 5925 5926 if (*buf){ 5927 if (strstr(buf,NVRAM_BEGIN_WEBFILE)) break; 5928 } 5929 5930 } 5931 5932 if (!len) return; 5933 5934 /* loop thru the header lines until we get the blank line 5935 that signifies the start of file contents */ 5936 while (len > 0){ 5937 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 5938 return; 5939 /* Remove LF that fgets()drags in */ 5940 len=remove_crlf(buf,len); 5941 5942 /* look for the blank line */ 5943 if (*buf == NVRAM_END_WEBFILE) break; 5944 } 5945 5946 if (!len) return; 5947 5948 /* Found start of upload file. Proceed with the upload */ 5949 /* Look for start of upload data */ 5950 if (!fgets(buf, MIN(len + 1, sizeof(buf)), stream)) 5951 return; 5952 5953 len = len - strlen(buf); 5954 5955 /* Get the number of NVRAM variables */ 5956 sprintf(tmp,"%s=%s",nvram_file_header[NVRAM_LINECOUNT_LINENUM],"%d"); 5957 5958 if ( (sscanf(buf,tmp,&numlines) != 1) || !len ){ 5959 strncpy(posterr_msg,"Invalid NVRAM header<br>",ERR_MSG_SIZE); 5960 return ; 5961 } 5962 5963 if ((numlines > NVRAM_MAX_LINES ) || !numlines ){ 5964 strncpy(posterr_msg,"Invalid NVRAM header<br>",ERR_MSG_SIZE); 5965 return; 5966 } 5967 5968 tmpbuf = (struct pb *) malloc( sizeof(struct pb)); 5969 if (!tmpbuf){ 5970 strncpy(posterr_msg,"Memory allocation error<br>",ERR_MSG_SIZE); 5971 return; 5972 } 5973 5974 memset(tmpbuf,0,sizeof(struct pb)); 5975 5976 /* Copy over the first line of the file. Needed for 5977 proper checksum calculations */ 5978 5979 strcpy(tmpbuf->header[0],buf); 5980 5981 /* read in checksum */ 5982 if (!fgets(tmpbuf->header[1], MIN(len + 1,NVRAM_MAX_STRINGSIZE), stream)) 5983 goto do_nvramul_post_cleanup0; 5984 5985 len = len - strlen(tmpbuf->header[1]); 5986 5987 /* start reading in the rest of the NVRAM contents into memory buffer*/ 5988 offset = 0; 5989 for (index = 2 ; (len > 0) && (index < numlines); index++){ 5990 char filebuf[NVRAM_MAX_STRINGSIZE]; 5991 5992 if (!fgets(filebuf, MIN(len + 1,NVRAM_MAX_STRINGSIZE), stream)) 5993 goto do_nvramul_post_cleanup0; 5994 5995 offset = add_string(&tmpbuf->buf[offset],filebuf,offset, 5996 sizeof(((struct pb *)0)->buf)); 5997 if (offset < 0){ 5998 snprintf(posterr_msg,ERR_MSG_SIZE, 5999 "Error processing NVRAM variable:%s<br>",filebuf); 6000 goto do_nvramul_post_cleanup0; 6001 } 6002 len = len - strlen(filebuf); 6003 6004 /* don't remove the LFs since the we are using multipart 6005 MIME encoding that does not touch the contents of the 6006 uploaded file. LFs are actually part of the NVRAM var lines. 6007 */ 6008 } 6009 6010 /* Bail if the number of actual lines is less than that 6011 in the header 6012 */ 6013 6014 if ( !len && (index < numlines) ){ 6015 strncpy(posterr_msg,"NVRAM file incomplete<br>",ERR_MSG_SIZE); 6016 goto do_nvramul_post_cleanup0; 6017 } 6018 6019 /* Save and decode checksum from file */ 6020 ptr = tmpbuf->header[checksum_linenum]; 6021 6022 sprintf(tmp,"%s=",nvram_file_header[checksum_linenum]); 6023 6024 if ( !strstr(ptr,tmp) ) { 6025 snprintf(posterr_msg,ERR_MSG_SIZE, 6026 "No checksum present at line %d<br>",checksum_linenum+1); 6027 goto do_nvramul_post_cleanup0 ; 6028 } 6029 ptr = &ptr[strlen(tmp)]; 6030 6031 if ( b64_decode(ptr,tmp,NVRAM_MAX_STRINGSIZE) != NVRAM_FILECHKSUM_SIZE){ 6032 strncpy(posterr_msg,"Invalid checksum.<br>",ERR_MSG_SIZE); 6033 goto do_nvramul_post_cleanup0 ; 6034 }; 6035 6036 memset(file_checksum,0,sizeof(file_checksum)); 6037 memcpy(file_checksum,tmp,NVRAM_HASHSIZE); 6038 6039 /* Extract salt value from stored checksum*/ 6040 memcpy(salt,&tmp[NVRAM_HASHSIZE],NVRAM_SALTSIZE); 6041 6042 /* Regenerate encryption key */ 6043 memset(key,0,NVRAM_FILEKEYSIZE); 6044 fPRF(passphrase,strlen(passphrase),NULL,0, 6045 (unsigned char*)salt,sizeof(salt),key,sizeof(key)); 6046 6047 /* Plug in filler for checksum into read buffer*/ 6048 memset(tmpbuf->header[checksum_linenum],0,NVRAM_MAX_STRINGSIZE); 6049 snprintf(tmpbuf->header[checksum_linenum], 6050 NVRAM_MAX_STRINGSIZE,"%s\n",NVRAM_CHECKSUM_FILLER); 6051 6052 /* Calculate checksum and compare with stored value*/ 6053 6054 memset(checksum,0,sizeof(checksum)); 6055 hmac_sha1((unsigned char*)tmpbuf,sizeof(struct pb) , 6056 key,sizeof(key),checksum); 6057 6058 if (memcmp(checksum,file_checksum,NVRAM_HASHSIZE)){ 6059 memcpy(posterr_msg,"File checksum error<br>",ERR_MSG_SIZE); 6060 goto do_nvramul_post_cleanup0; 6061 } 6062 6063 /* Check constraints on the data */ 6064 6065 cur_entry = NVRAM_HEADER_LINECOUNT(nvram_file_header); 6066 slen=0; 6067 name = tmpbuf->buf; 6068 for (index = 0 ; *constraint_vars[index].name && *name; index++,cur_entry++,name += slen + 1) { 6069 char *var=NULL,*ptr=NULL; 6070 int comparesize ; 6071 6072 slen = strlen(name); 6073 6074 if (cur_entry > numlines){ 6075 memcpy(posterr_msg, 6076 "Constraints mismatch between file and running image<br>", 6077 ERR_MSG_SIZE); 6078 goto do_nvramul_post_cleanup0; 6079 } 6080 6081 6082 var = constraint_vars[index].get(constraint_vars[index].name); 6083 6084 if (!var){ 6085 snprintf(posterr_msg,ERR_MSG_SIZE, 6086 "NVRAM variable:%s not found in running image<br>", 6087 constraint_vars[index].name); 6088 goto do_nvramul_post_cleanup0; 6089 } 6090 6091 if (!strstr(name,constraint_vars[index].name)){ 6092 snprintf(posterr_msg,ERR_MSG_SIZE, 6093 "NVRAM variable:%s not found in uploaded file<br>", 6094 constraint_vars[index].name); 6095 goto do_nvramul_post_cleanup0; 6096 } 6097 6098 /*Move past separator*/ 6099 ptr = &name[strlen(constraint_vars[index].name) + 1] ; 6100 6101 /* Ignore last character which is a \n */ 6102 comparesize = strlen(ptr) -1; 6103 6104 /* If the primary match fails try for the secomdary matches */ 6105 if (strncmp(ptr,var,comparesize)){ 6106 int sec_fail=0; 6107 6108 /* If partial march is defined match altval pattern against 6109 file and image values*/ 6110 if (constraint_vars[index].flags & NVRAM_CONS_PARTIAL_MATCH){ 6111 sec_fail=( !strstr(ptr,constraint_vars[index].altval) && 6112 !strstr(var,constraint_vars[index].altval)); 6113 } 6114 else if (constraint_vars[index].flags & NVRAM_CONS_ALT_MATCH){ 6115 sec_fail=(strncmp(ptr,constraint_vars[index].altval,comparesize)); 6116 } 6117 else sec_fail =1; 6118 6119 if (sec_fail){ 6120 snprintf(posterr_msg,ERR_MSG_SIZE, 6121 "NVRAM constraint mismatch FILE:<b>%s=%s</b> IMAGE:<b>%s=%s</b><br>", 6122 constraint_vars[index].name,ptr,constraint_vars[index].name,var); 6123 goto do_nvramul_post_cleanup0; 6124 } 6125 } 6126 6127 } 6128 6129 /* Process the NVRAM payload 6130 * 6131 * Remove the carriage returns at the end of the NVRAM variables 6132 * 6133 */ 6134 6135 cur_entry = NVRAM_HEADER_LINECOUNT(nvram_file_header) + NVRAM_HEADER_LINECOUNT(constraint_vars); 6136 6137 slen=0; 6138 for (index = cur_entry ;(index < numlines) && *name; index++,name += slen + 1){ 6139 int offset; 6140 char *ptr=NULL; 6141 char *varname=NULL; 6142 char *myptr=NULL; 6143 struct variable *v=NULL; 6144 6145 offset = index * NVRAM_MAX_STRINGSIZE; 6146 6147 /* The length of the actual var must be saved here as the subsequent 6148 * manipulation using strsep() changes the string buffer. 6149 * This to ensure that the buffer (tmpbuf->buf) is correctly procesed 6150 * This buffer separates the individual AVPs using a null character 6151 */ 6152 6153 slen =strlen(name); 6154 ptr = name; 6155 6156 /* Remove the CR at the end of the string */ 6157 ptr[slen-1] = '\0'; 6158 6159 /* Look for tag that indicates that the value is encrypted */ 6160 if (*ptr==NVRAM_ENCTAG){ 6161 char buf[NVRAM_MAX_STRINGSIZE]; 6162 int bufsize = sizeof(buf); 6163 char *varname=NULL; 6164 6165 varname=strsep(&ptr, "="); 6166 6167 /* Increment pointer to move past tag */ 6168 varname++; 6169 6170 if (!decrypt_var(varname,ptr,strlen(ptr),buf,&bufsize,key,sizeof(key))){ 6171 snprintf(posterr_msg,ERR_MSG_SIZE, 6172 "Error decrypting value %s at line %d<br>",ptr,index); 6173 goto do_nvramul_post_cleanup0; 6174 } 6175 6176 snprintf(name,NVRAM_MAX_STRINGSIZE,"%s=%s",varname,buf); 6177 6178 } 6179 6180 /* 6181 Write out NVRAM variables. 6182 */ 6183 6184 myptr = name; 6185 varname=strsep(&myptr, "="); 6186 6187 v=get_var_handle(varname); 6188 6189 /* Restore only those NVRAM vars in the validation table 6190 Ignore those with the obvious flag set 6191 */ 6192 6193 if (!v) 6194 continue; 6195 6196 if (v->ezc_flags & NVRAM_IGNORE) 6197 continue; 6198 6199 if (nvram_set(varname,myptr)) 6200 goto do_nvramul_post_cleanup0; 6201 6202 } 6203 6204 nvram_commit(); 6205 6206 /* We are done */ 6207 ret_code = 0; 6208 6209do_nvramul_post_cleanup0: 6210 /* Clear up any outstanding stuff */ 6211 /* Slurp anything remaining in the request */ 6212 while (len--) 6213 (void) fgetc(stream); 6214 6215 if (tmpbuf) free(tmpbuf); 6216 6217 return; 6218} 6219 6220static void 6221do_nvramul_cgi(char *url, FILE *stream) 6222{ 6223 assert(stream); 6224 assert(url); 6225 6226 websHeader(stream); 6227 websWrite(stream, (char_t *) apply_header); 6228 6229 if (ret_code){ 6230 websWrite(stream, "Error during NVRAM upload<br>"); 6231 if (*posterr_msg){ 6232 websWrite(stream, posterr_msg); 6233 memset(posterr_msg,0,ERR_MSG_SIZE); 6234 } 6235 6236 } else websWrite(stream, "NVRAM upload complete.<br>Rebooting....<br>"); 6237 6238 websWrite(stream, (char_t *) apply_footer, "firmware.asp"); 6239 websFooter(stream); 6240 websDone(stream, 200); 6241 6242 /* Reboot if successful */ 6243 if (ret_code == 0) 6244 sys_reboot(); 6245 6246} 6247 6248/* 6249 This routine validates and formats the NVRAM variable into the file output format. 6250 If the variable is not in the monster V-block or its allowed multi instance variants 6251 it is dropped 6252 6253 Returns number of characters printed or -1 on error 6254*/ 6255static int 6256save_nvram_var(char *name, char *var_val,char *buf, int buflen,char *key, int keylen) 6257{ 6258 char tmp[NVRAM_MAX_STRINGSIZE]; 6259 int len=sizeof(tmp); 6260 int retval=0; 6261 struct variable *v = NULL; 6262 6263 assert(name); 6264 assert(buf); 6265 assert(key); 6266 assert(buflen); 6267 assert(keylen); 6268 6269 6270 /* If var_val is null, this forces the variable to be unset when the file is uploaded 6271 If the variable is supposed to be encrypted but is null, skip it and do not 6272 mark the string as encrypted. 6273 6274 If var_val is null the variable does not exist. Skip and do not save in that case. 6275 */ 6276 6277 v = get_var_handle(name); 6278 6279 if (!v) 6280 return 0; 6281 6282 if (v->ezc_flags & NVRAM_IGNORE) 6283 return 0; 6284 6285 if (var_val) { 6286 if (strlen(var_val) > NVRAM_MAX_STRINGSIZE){ 6287 cprintf("get_nvram_var():String too long Len=%d String=%s\n", strlen(var_val) ,var_val); 6288 return -1; 6289 } 6290 6291 if ( (v->ezc_flags & NVRAM_ENCRYPT) && (*var_val) ){ 6292 var_val = encrypt_var(name,var_val,strlen(var_val),tmp,&len,key,keylen); 6293 6294 if (!var_val){ 6295 cprintf("get_nvram_var():Error encrypting %s\n",name); 6296 return -1; 6297 } 6298 6299 retval=snprintf(buf,buflen,"%c%s=%s\n", 6300 NVRAM_ENCTAG, 6301 (char_t *)name, 6302 (char_t *)var_val); 6303 } else retval=snprintf(buf,buflen,"%s=%s\n", 6304 (char_t *)name, 6305 (char_t *)var_val); 6306 } 6307 return retval; 6308} 6309 6310/* This is the cgi handler for the NVRAM download function 6311 * Inputs: -url of the calling file (not used but HTTPD expects this form) 6312 * -Pointer to the post buffer 6313 * 6314 * 6315 * Returns: None 6316*/ 6317static void 6318do_nvramdl_cgi(char *url, FILE *stream) 6319{ 6320 char checksum[NVRAM_SHA1BUFSIZE]; 6321 char passphrase[]=NVRAM_PASSPHRASE; 6322 char salt[NVRAM_SALTSIZE]; 6323 char key[NVRAM_FILEKEYSIZE]; 6324 int entries; 6325 char tmp[NVRAM_MAX_STRINGSIZE],tmp1[NVRAM_MAX_STRINGSIZE]; 6326 char tmp_buf[NVRAM_MAX_STRINGSIZE]; 6327 char *buf=NULL; 6328 char *var_val=NULL; 6329 char *var_name=NULL; 6330 char *name=NULL; 6331 char *ptr=NULL; 6332 int index; 6333 int retval; 6334 upload_constraints constraint_vars [] = NVRAM_CONSTRAINT_VARS; 6335 char nvram_file_header[][NVRAM_MAX_STRINGSIZE/2] = NVRAM_FILEHEADER; 6336 struct pb { 6337 char header[NVRAM_HEADER_LINECOUNT(nvram_file_header)][NVRAM_MAX_STRINGSIZE]; 6338 char buf[NVRAM_SPACE]; 6339 } *post_buf=NULL; 6340 6341 int offset = 0; 6342 6343 assert(stream); 6344 6345 post_buf = (struct pb *)malloc(sizeof (struct pb)); 6346 6347 if (!post_buf) { 6348 cprintf("do_nvramdl_cgi():Error allocating %d bytes for post_buf\n", 6349 sizeof (struct pb)); 6350 goto do_nvramdl_cgi_error; 6351 } 6352 6353 buf = (char *)malloc(NVRAM_SPACE); 6354 6355 if (!buf) { 6356 cprintf("do_nvramdl_cgi():Error allocating %d bytes for buf\n", 6357 NVRAM_SPACE); 6358 goto do_nvramdl_cgi_error; 6359 } 6360 6361 memset (post_buf,0,sizeof(struct pb)); 6362 memset (buf,0,NVRAM_SPACE); 6363 6364 assert(stream); 6365 6366 entries = NVRAM_HEADER_LINECOUNT(nvram_file_header); 6367 memset(tmp_buf,0,sizeof(tmp_buf)); 6368 6369 memset(salt,0,sizeof(salt)); 6370 6371 srand(time((time_t *)NULL)); 6372 for (index = 0 ; index < 30 ; index ++) rand(); 6373 index =rand(); 6374 memcpy(&salt[sizeof(index)],&index,sizeof(index)); 6375 for (index = 0 ; index < 30 ; index ++) rand(); 6376 index =rand(); 6377 memcpy(&salt,&index,sizeof(index)); 6378 6379 /* 6380 The first entry of the file is the number of variables 6381 The second entry is the offset to the start of the NVRAM variables 6382 The third entry is the SHA1 checksum 6383 */ 6384 6385 /* PopulateHeader info */ 6386 offset = 0; 6387 for (index =0 ;*constraint_vars[index].name;index++){ 6388 entries++; 6389 var_val=constraint_vars[index].get(constraint_vars[index].name); 6390 snprintf(tmp_buf,NVRAM_MAX_STRINGSIZE,"%s=%s\n", 6391 constraint_vars[index].name, 6392 (var_val) ? var_val : "unknown"); 6393 if (!offset) cprintf("Post_buf address = %p\n",&post_buf->buf[offset]); 6394 offset = add_string(&post_buf->buf[offset],tmp_buf,offset,sizeof(struct pb)); 6395 if (offset < 0){ 6396 cprintf("httpd: Error Adding NVRAM header info.\n"); 6397 goto do_nvramdl_cgi_error; 6398 } 6399 }; 6400 6401 memset(tmp,0,sizeof(tmp)); 6402 6403 fPRF(passphrase,strlen(passphrase),NULL,0, 6404 (unsigned char*)salt,sizeof(salt),key,sizeof(key)); 6405 6406 /* Plug in filler for checksum */ 6407 snprintf(post_buf->header[NVRAM_CHECKSUM_LINENUM],NVRAM_MAX_STRINGSIZE,"%s\n",NVRAM_CHECKSUM_FILLER); 6408 /* Grab the NVRAM buffer */ 6409 6410 nvram_getall(buf, NVRAM_SPACE); 6411 6412 for(name = buf; *name; name += strlen(name) + 1){ 6413 var_val =tmp; 6414 strncpy(tmp,name,sizeof(tmp)); 6415 var_name=strsep(&var_val,"="); 6416 retval = save_nvram_var(var_name,var_val,tmp_buf, 6417 sizeof(tmp_buf),key,sizeof(key)); 6418 6419 if (retval <0){ 6420 cprintf("httpd: Error Adding NVRAM variable info.\n"); 6421 goto do_nvramdl_cgi_error; 6422 }; 6423 6424 if (retval > 0 ) { 6425 entries++; 6426 offset = add_string(&post_buf->buf[offset],tmp_buf,offset,sizeof(struct pb)); 6427 if (offset < 0){ 6428 cprintf("httpd: Error Adding NVRAM variable info.\n"); 6429 goto do_nvramdl_cgi_error; 6430 } 6431 }; 6432 6433 if (offset > NVRAM_SPACE) { 6434 cprintf("httpd: NVRAM_SPACE of %d (%d) exceeded\n",NVRAM_SPACE,offset); 6435 goto do_nvramdl_cgi_error; 6436 }; 6437 } 6438 6439 6440 /* Add the header info */ 6441 snprintf(post_buf->header[NVRAM_LINECOUNT_LINENUM],NVRAM_MAX_STRINGSIZE,"%s=%d\n", 6442 nvram_file_header[NVRAM_LINECOUNT_LINENUM],entries); 6443 6444 /*Generate the hash */ 6445 6446 memset(checksum,0,sizeof(checksum)); 6447 hmac_sha1((unsigned char*)post_buf,sizeof(struct pb),key,sizeof(key),checksum); 6448 6449 memcpy(tmp,checksum,NVRAM_HASHSIZE); 6450 memcpy(&tmp[NVRAM_HASHSIZE],salt,NVRAM_SALTSIZE); 6451 6452 ptr = b64_encode(tmp,NVRAM_FILECHKSUM_SIZE, buf, NVRAM_SPACE ); 6453 6454 if (!ptr){ 6455 cprintf("do_nvramdl_cgi():Error performing base-64 encode of NVRAM checksum.\n"); 6456 goto do_nvramdl_cgi_error; 6457 } 6458 6459 strncpy(tmp1,ptr,NVRAM_MAX_STRINGSIZE); 6460 6461 snprintf(post_buf->header[NVRAM_CHECKSUM_LINENUM],NVRAM_MAX_STRINGSIZE,"%s=%s\n", 6462 nvram_file_header[NVRAM_CHECKSUM_LINENUM],tmp1); 6463 /* Write out header */ 6464 for (index =0; index < NVRAM_HEADER_LINECOUNT(nvram_file_header) ; index ++) 6465 websWrite(stream, "%s", post_buf->header[index]); 6466 6467 /* Write out rest of file */ 6468 6469 for(name = post_buf->buf; *name; name += strlen(name) + 1){ 6470 /*cprintf("Val->%s\n",name);*/ 6471 websWrite(stream, "%s", name); 6472 }; 6473 6474do_nvramdl_cgi_error: 6475 6476 if (post_buf) 6477 free(post_buf); 6478 if (buf) 6479 free(buf); 6480 6481 websDone(stream, 200); 6482 6483 return; 6484} 6485 6486 6487/* 6488 * This routine takes the cipher text ctext and produces the plaintext ptext 6489 * using the provided key. 6490 * 6491 * This routine accepts the cipher text in the MIME Base64 format. 6492 * 6493 * The plain text is 8 bytes less than the ciphertext 6494 */ 6495static char* 6496decrypt_var(char *varname,char *ctext, int ctext_len, char *ptext, int *ptext_len,char *key, int keylen) 6497{ 6498 unsigned char tmp[NVRAM_MAX_STRINGSIZE]; 6499 int len; 6500 char *end=NULL; 6501 6502 assert(ptext); 6503 assert(ctext); 6504 assert(ptext_len); 6505 assert(key); 6506 if (keylen < 1 ) return NULL; 6507 6508 if (ctext_len > NVRAM_MAX_STRINGSIZE){ 6509 cprintf("decrypt_var():Encrypted string is too long MAXSTRINGSIZE=%d Strlen=%d\n", 6510 NVRAM_MAX_STRINGSIZE,ctext_len); 6511 } 6512 6513 /* Cipher text must be more than 8 chars for this aes_unwrap() routine to work*/ 6514 if (ctext_len < 8) return NULL; 6515 6516 len=b64_decode(ctext,tmp,NVRAM_MAX_STRINGSIZE); 6517 6518 if (!len) return NULL; 6519 6520 if (aes_unwrap(keylen,key,len,tmp,ptext)) return NULL; 6521 6522 *ptext_len = len - 8; 6523 6524 end = strstr(ptext,varname); 6525 6526 if (end) 6527 (*end)= '\0'; 6528 else 6529 return NULL; 6530 6531 return ptext; 6532} 6533/* 6534 * This routine takes the plaintext text ptext and produces the ciphertext ctext 6535 * using the provided key. 6536 * 6537 * It accepts the plaintext in binary form and produces ciphertext in MIME Base64 format. 6538 * 6539 * 6540 */ 6541static char* 6542encrypt_var(char *varname,char *ptext, int ptext_len, char *ctext, int *ctext_len,char *key, int keylen) 6543{ 6544 unsigned char tmp[NVRAM_MAX_STRINGSIZE]; 6545 char *buf=NULL; 6546 int newlen; 6547 int varname_len; 6548 6549 assert(ptext); 6550 assert(ctext); 6551 assert(ctext_len); 6552 assert(key); 6553 if (keylen < 1 ) return NULL; 6554 if (ptext_len < 1) return NULL; 6555 6556 varname_len = strlen (varname); 6557 6558 /* Include the NULL at the end */ 6559 newlen = ptext_len + varname_len + 1; 6560 /* Align the incoming buffer to AES block length boundaries */ 6561 if (newlen % AES_BLOCK_LEN) 6562 newlen = (1 + newlen /AES_BLOCK_LEN ) * AES_BLOCK_LEN; 6563 6564 /* Do a string length check. When the binary string is base-64 encoded 6565 it becomes 30% larger as every 3 bytes are represented by 4 ascii 6566 characters */ 6567 6568 if ( (4*(1+(newlen+8)/3)) > NVRAM_MAX_STRINGSIZE ) 6569 { 6570 cprintf("encrypt_var():The encrypted string is too long. MAXSTRINGSIZE=%d Strlen=%d\n", 6571 NVRAM_MAX_STRINGSIZE,(4*(1+(newlen+8)/3))); 6572 return NULL; 6573 } 6574 6575 buf = malloc (newlen); 6576 if (!buf) return NULL; 6577 memset(buf,0,newlen); 6578 memcpy(buf,ptext,ptext_len); 6579 memcpy(buf + ptext_len,varname,varname_len); 6580 6581 if (aes_wrap(keylen,key,newlen,buf,ctext)){ 6582 if (buf) free(buf); 6583 return NULL; 6584 }; 6585 6586 if (buf) free(buf); 6587 6588 buf = b64_encode(ctext,newlen+8,tmp,NVRAM_MAX_STRINGSIZE-(ptext_len + 1)); 6589 6590 if (buf){ 6591 strncpy(ctext,buf,NVRAM_MAX_STRINGSIZE); 6592 *ctext_len = strlen(ctext) ; 6593 return ctext; 6594 }else{ 6595 cprintf("encrypt_var():base-64 encode error\n"); 6596 *ctext_len = 0; 6597 return NULL; 6598 } 6599} 6600 6601 6602static void 6603do_wireless_asp(char *url, FILE *stream) 6604{ 6605 char *path=NULL, *query=NULL; 6606 6607 assert(stream); 6608 assert(url); 6609 6610 /* Parse path */ 6611 query = url; 6612 path = strsep(&query, "?") ? : url; 6613 6614 copy_wl_index_to_unindex(stream, NULL, NULL, 0, url, path, query); 6615 6616 /* Reset CGI */ 6617 init_cgi(NULL); 6618} 6619 6620static void 6621do_security_asp(char *url, FILE *stream) 6622{ 6623 char *path=NULL, *query=NULL; 6624 6625 assert(stream); 6626 assert(url); 6627 6628 /* Parse path */ 6629 query = url; 6630 path = strsep(&query, "?") ? : url; 6631 6632 copy_wl_index_to_unindex(stream, NULL, NULL, 0, url, path, query); 6633 6634 /* Reset CGI */ 6635 init_cgi(NULL); 6636} 6637 6638static void 6639do_internal_asp(char *url, FILE *stream) 6640{ 6641 char *path=NULL, *query=NULL; 6642 6643 assert(stream); 6644 assert(url); 6645 6646 /* Parse path */ 6647 query = url; 6648 path = strsep(&query, "?") ? : url; 6649 6650 copy_wl_index_to_unindex(stream, NULL, NULL, 0, url, path, query); 6651 6652 /* Reset CGI */ 6653 init_cgi(NULL); 6654} 6655 6656#ifdef __CONFIG_NAT__ 6657static void 6658do_wan_asp(char *url, FILE *stream) 6659{ 6660 char *path=NULL, *query=NULL; 6661 6662 assert(stream); 6663 assert(url); 6664 6665 /* Parse path */ 6666 query = url; 6667 path = strsep(&query, "?") ? : url; 6668 6669 wan_asp(stream, NULL, NULL, 0, url, path, query); 6670 6671 /* Reset CGI */ 6672 init_cgi(NULL); 6673} 6674#endif /* __CONFIG_NAT__ */ 6675 6676struct mime_handler mime_handlers[] = { 6677#ifdef __CONFIG_NAT__ 6678 { "wan.asp", "text/html", no_cache, do_apply_post, do_wan_asp, do_auth }, 6679#endif /* __CONFIG_NAT__ */ 6680 { "wireless.asp", "text/html", no_cache, do_apply_post, do_wireless_asp, do_auth }, 6681 { "security.asp", "text/html", no_cache, do_apply_post, do_security_asp, do_auth }, 6682 { "internal.asp", "text/html", no_cache, do_apply_post, do_internal_asp, do_auth }, 6683#ifdef __CONFIG_EZC__ 6684 { "ezconfig.asp", "text/html", ezc_version, do_apply_ezconfig_post, do_ezconfig_asp, do_auth }, 6685#endif /* __CONFIG_EZC__ */ 6686 { "**.asp", "text/html", no_cache, NULL, do_ej, do_auth }, 6687 { "**.css", "text/css", NULL, NULL, do_file, do_auth }, 6688 { "**.gif", "image/gif", NULL, NULL, do_file, do_auth }, 6689 { "**.jpg", "image/jpeg", NULL, NULL, do_file, do_auth }, 6690 { "**.js", "text/javascript", NULL, NULL, do_file, do_auth }, 6691 { "apply.cgi*", "text/html", no_cache, do_apply_post, do_apply_cgi, do_auth }, 6692 { "upgrade.cgi*", "text/html", no_cache, do_upgrade_post, do_upgrade_cgi, do_auth }, 6693 /* set MIME type to NULL to override the one built into the webserver. download_hdr 6694 defines its content type 6695 */ 6696 { "nvramdl.cgi*", NULL, download_hdr, NULL, do_nvramdl_cgi, do_auth }, 6697 { "nvramul.cgi*", NULL, "text/html", do_nvramul_post,do_nvramul_cgi , do_auth }, 6698 { NULL, NULL, NULL, NULL, NULL, NULL } 6699}; 6700 6701struct ej_handler ej_handlers[] = { 6702 { "nvram_get", ej_nvram_get }, 6703 { "nvram_match", ej_nvram_match }, 6704 { "nvram_invmatch", ej_nvram_invmatch }, 6705 { "nvram_list", ej_nvram_list }, 6706 { "nvram_inlist", ej_nvram_inlist }, 6707 { "nvram_invinlist", ej_nvram_invinlist }, 6708#ifdef __CONFIG_NAT__ 6709 { "wan_list", ej_wan_list }, 6710 { "wan_iflist", ej_wan_iflist }, 6711 { "wan_route", ej_wan_route }, 6712 { "wan_link", ej_wan_link }, 6713 { "wan_lease", ej_wan_lease }, 6714 { "filter_client", ej_filter_client }, 6715 { "forward_port", ej_forward_port }, 6716 { "autofw_port", ej_autofw_port }, 6717#endif /* __CONFIG_NAT__ */ 6718 { "localtime", ej_localtime }, 6719 { "sysuptime", ej_sysuptime }, 6720 { "dumplog", ej_dumplog }, 6721 { "syslog", ej_syslog }, 6722 { "wl_list", ej_wl_list }, 6723 { "wl_guest_ssid", ej_wl_guest_ssid}, 6724 { "wl_phytypes", ej_wl_phytypes }, 6725 { "wl_radioid", ej_wl_radioid }, 6726 { "wl_corerev", ej_wl_corerev }, 6727 { "wl_cur_channel", ej_wl_cur_channel }, 6728 { "wl_cur_phytype", ej_wl_cur_phytype }, 6729 { "wl_cur_country", ej_wl_cur_country }, 6730 { "wl_country_list", ej_wl_country_list }, 6731 { "wl_channel_list", ej_wl_channel_list }, 6732 { "wl_auth_list", ej_wl_auth_list }, 6733 { "wl_mode_list", ej_wl_mode_list }, 6734 { "wl_inlist", ej_wl_inlist }, 6735 { "wl_wds_status", ej_wl_wds_status }, 6736 { "wl_radio_roam_option", ej_wl_radio_roam_option}, 6737 { "wl_radio_roam_option", ej_wl_radio_roam_option}, 6738 { "wl_ure_list", ej_ure_list }, 6739 { "wl_ure_enabled", ej_ure_enabled }, 6740 { "ses_button_display", ej_ses_button_display}, 6741 { "ses_cl_button_display", ej_ses_cl_button_display}, 6742 { "lan_route", ej_lan_route }, 6743 { "lan_guest_iflist", ej_lan_guest_iflist }, 6744 { "lan_leases", ej_lan_leases }, 6745 { "asp_list", ej_asp_list }, 6746 { "wme_match_op", ej_wme_match_op }, 6747 { NULL, NULL } 6748}; 6749 6750#endif /* !WEBS */ 6751 6752/* 6753 * Country names and abbreviations from ISO 3166 6754 */ 6755country_name_t country_names[] = { 6756 6757{"COUNTRY Z1", "Z1"}, 6758{"COUNTRY Z2", "Z2"}, 6759{"AFGHANISTAN", "AF"}, 6760{"ALBANIA", "AL"}, 6761{"ALGERIA", "DZ"}, 6762{"AMERICAN SAMOA", "AS"}, 6763{"ANDORRA", "AD"}, 6764{"ANGOLA", "AO"}, 6765{"ANGUILLA", "AI"}, 6766{"ANTARCTICA", "AQ"}, 6767{"ANTIGUA AND BARBUDA", "AG"}, 6768{"ARGENTINA", "AR"}, 6769{"ARMENIA", "AM"}, 6770{"ARUBA", "AW"}, 6771{"ASCENSION ISLAND", "AC"}, 6772{"ASHMORE AND BARBUDA", "AG"}, 6773{"AUSTRALIA", "AU"}, 6774{"AUSTRIA", "AT"}, 6775{"AZERBAIJAN", "AZ"}, 6776{"BAHAMAS", "BS"}, 6777{"BAHRAIN", "BH"}, 6778{"BAKER ISLAND", "Z2"}, 6779{"BANGLADESH", "BD"}, 6780{"BARBADOS", "BB"}, 6781{"BELARUS", "BY"}, 6782{"BELGIUM", "BE"}, 6783{"BELIZE", "BZ"}, 6784{"BENIN", "BJ"}, 6785{"BERMUDA", "BM"}, 6786{"BHUTAN", "BT"}, 6787{"BOLIVIA", "BO"}, 6788{"BOSNIA AND HERZEGOVINA","BA"}, 6789{"BOTSWANA", "BW"}, 6790{"BOUVET ISLAND", "BV"}, 6791{"BRAZIL", "BR"}, 6792{"BRITISH INDIAN OCEAN TERRITORY", "IO"}, 6793{"BRUNEI DARUSSALAM", "BN"}, 6794{"BULGARIA", "BG"}, 6795{"BURKINA FASO", "BF"}, 6796{"BURUNDI", "BI"}, 6797{"CAMBODIA", "KH"}, 6798{"CAMEROON", "CM"}, 6799{"CANADA", "CA"}, 6800{"CAPE VERDE", "CV"}, 6801{"CAYMAN ISLANDS", "KY"}, 6802{"CENTRAL AFRICAN REPUBLIC","CF"}, 6803{"CHAD", "TD"}, 6804{"CHANNEL ISLANDS", "Z1"}, 6805{"CHILE", "CL"}, 6806{"CHINA", "CN"}, 6807{"CHRISTMAS ISLAND", "CX"}, 6808{"CLIPPERTON ISLAND", "CP"}, 6809{"COCOS (KEELING) ISLANDS","CC"}, 6810{"COLOMBIA", "CO"}, 6811{"COMOROS", "KM"}, 6812{"CONGO", "CG"}, 6813{"CONGO, THE DEMOCRATIC REPUBLIC OF THE", "CD"}, 6814{"COOK ISLANDS", "CK"}, 6815{"COSTA RICA", "CR"}, 6816{"COTE D'IVOIRE", "CI"}, 6817{"CROATIA", "HR"}, 6818{"CUBA", "CU"}, 6819{"CYPRUS", "CY"}, 6820{"CZECH REPUBLIC", "CZ"}, 6821{"DENMARK", "DK"}, 6822{"DJIBOUTI", "DJ"}, 6823{"DOMINICA", "DM"}, 6824{"DOMINICAN REPUBLIC", "DO"}, 6825{"ECUADOR", "EC"}, 6826{"EGYPT", "EG"}, 6827{"EL SALVADOR", "SV"}, 6828{"EQUATORIAL GUINEA", "GQ"}, 6829{"ERITREA", "ER"}, 6830{"ESTONIA", "EE"}, 6831{"ETHIOPIA", "ET"}, 6832{"FALKLAND ISLANDS (MALVINAS)", "FK"}, 6833{"FAROE ISLANDS", "FO"}, 6834{"FIJI", "FJ"}, 6835{"FINLAND", "FI"}, 6836{"FRANCE", "FR"}, 6837{"FRENCH GUIANA", "GF"}, 6838{"FRENCH POLYNESIA", "PF"}, 6839{"FRENCH SOUTHERN TERRITORIES", "TF"}, 6840{"GABON", "GA"}, 6841{"GAMBIA", "GM"}, 6842{"GEORGIA", "GE"}, 6843{"GERMANY", "DE"}, 6844{"GHANA", "GH"}, 6845{"GIBRALTAR", "GI"}, 6846{"GREECE", "GR"}, 6847{"GREENLAND", "GL"}, 6848{"GRENADA", "GD"}, 6849{"GUADELOUPE", "GP"}, 6850{"GUAM", "GU"}, 6851{"GUANTANAMO BAY", "Z1"}, 6852{"GUATEMALA", "GT"}, 6853{"GUERNSEY", "GG"}, 6854{"GUINEA", "GN"}, 6855{"GUINEA-BISSAU", "GW"}, 6856{"GUYANA", "GY"}, 6857{"HAITI", "HT"}, 6858{"HEARD ISLAND AND MCDONALD ISLANDS", "HM"}, 6859{"HOLY SEE (VATICAN CITY STATE)", "VA"}, 6860{"HONDURAS", "HN"}, 6861{"HONG KONG", "HK"}, 6862{"HOWLAND ISLAND", "Z2"}, 6863{"HUNGARY", "HU"}, 6864{"ICELAND", "IS"}, 6865{"INDIA", "IN"}, 6866{"INDONESIA", "ID"}, 6867{"IRAN, ISLAMIC REPUBLIC OF", "IR"}, 6868{"IRAQ", "IQ"}, 6869{"IRELAND", "IE"}, 6870{"ISRAEL", "IL"}, 6871{"ITALY", "IT"}, 6872{"JAMAICA", "JM"}, 6873{"JAN MAYEN AMAICA", "Z1"}, 6874{"JAPAN", "JP"}, 6875{"JAPAN_1", "J1"}, 6876{"JAPAN_2", "J2"}, 6877{"JAPAN_3", "J3"}, 6878{"JAPAN_4", "J4"}, 6879{"JAPAN_5", "J5"}, 6880{"JAPAN_6", "J6"}, 6881{"JAPAN_7", "J7"}, 6882{"JAPAN_8", "J8"}, 6883{"JARVIS ISLAND", "Z2"}, 6884{"JERSEY", "JE"}, 6885{"JOHNSTON ATOLL", "Z2"}, 6886{"JORDON", "JO"}, 6887{"KAZAKHSTAN", "KZ"}, 6888{"KENYA", "KE"}, 6889{"KINGMAN REEF", "Z2"}, 6890{"KIRIBATI", "KI"}, 6891{"KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF", "KP"}, 6892{"KOREA, REPUBLIC OF", "KR"}, 6893{"KUWAIT", "KW"}, 6894{"KYRGYZSTAN", "KG"}, 6895{"LAO PEOPLE'S DEMOCRATIC REPUBLIC", "LA"}, 6896{"LATVIA", "LV"}, 6897{"LEBANON", "LB"}, 6898{"LESOTHO", "LS"}, 6899{"LIBERIA", "LR"}, 6900{"LIBYAN ARAB JAMAHIRIYA","LY"}, 6901{"LIECHTENSTEIN", "LI"}, 6902{"LITHUANIA", "LT"}, 6903{"LUXEMBOURG", "LU"}, 6904{"MACAO", "MO"}, 6905{"MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF", "MK"}, 6906{"MADAGASCAR", "MG"}, 6907{"MALAWI", "MW"}, 6908{"MALAYSIA", "MY"}, 6909{"MALDIVES", "MV"}, 6910{"MALI", "ML"}, 6911{"MALTA", "MT"}, 6912{"MAN, ISLE OF", "IM"}, 6913{"MARSHALL ISLANDS", "MH"}, 6914{"MARTINIQUE", "MQ"}, 6915{"MAURITANIA", "MR"}, 6916{"MAURITIUS", "MU"}, 6917{"MAYOTTE", "YT"}, 6918{"MEXICO", "MX"}, 6919{"MICRONESIA, FEDERATED STATES OF", "FM"}, 6920{"MIDWAY ISLANDS", "Z2"}, 6921{"MOLDOVA, REPUBLIC OF", "MD"}, 6922{"MONACO", "MC"}, 6923{"MONGOLIA", "MN"}, 6924{"MONTSERRAT", "MS"}, 6925{"MOROCCO", "MA"}, 6926{"MOZAMBIQUE", "MZ"}, 6927{"MYANMAR", "MM"}, 6928{"NAMIBIA", "NA"}, 6929{"NAURU", "NR"}, 6930{"NEPAL", "NP"}, 6931{"NETHERLANDS", "NL"}, 6932{"NETHERLANDS ANTILLES", "AN"}, 6933{"NEW CALEDONIA", "NC"}, 6934{"NEW ZEALAND", "NZ"}, 6935{"NICARAGUA", "NI"}, 6936{"NIGER", "NE"}, 6937{"NIGERIA", "NG"}, 6938{"NIUE", "NU"}, 6939{"NORFOLK ISLAND", "NF"}, 6940{"NORTHERN MARIANA ISLANDS","MP"}, 6941{"NORWAY", "NO"}, 6942{"OMAN", "OM"}, 6943{"PAKISTAN", "PK"}, 6944{"PALAU", "PW"}, 6945{"PALESTINIAN TERRITORY, OCCUPIED", "PS"}, 6946{"PALMYRA ATOLL", "Z2"}, 6947{"PANAMA", "PA"}, 6948{"PAPUA NEW GUINEA", "PG"}, 6949{"PARAGUAY", "PY"}, 6950{"PERU", "PE"}, 6951{"PHILIPPINES", "PH"}, 6952{"PITCAIRN", "PN"}, 6953{"POLAND", "PL"}, 6954{"PORTUGAL", "PT"}, 6955{"PUERTO RICO", "PR"}, 6956{"QATAR", "QA"}, 6957{"REUNION", "RE"}, 6958{"ROMANIA", "RO"}, 6959{"ROTA ISLAND", "Z1"}, 6960{"RUSSIAN FEDERATION", "RU"}, 6961{"RWANDA", "RW"}, 6962{"SAINT HELENA", "SH"}, 6963{"SAINT KITTS AND NEVIS","KN"}, 6964{"SAINT LUCIA", "LC"}, 6965{"SAINT PIERRE AND MIQUELON", "PM"}, 6966{"SAINT VINCENT AND THE GRENADINES", "VC"}, 6967{"SAIPAN", "Z1"}, 6968{"SAMOA", "WS"}, 6969{"SAN MARINO", "SM"}, 6970{"SAO TOME AND PRINCIPE","ST"}, 6971{"SAUDI ARABIA", "SA"}, 6972{"SENEGAL", "SN"}, 6973{"SEYCHELLES", "SC"}, 6974{"SIERRA LEONE", "SL"}, 6975{"SINGAPORE", "SG"}, 6976{"SLOVAKIA", "SK"}, 6977{"SLOVENIA", "SI"}, 6978{"SOLOMON ISLANDS", "SB"}, 6979{"SOMALIA", "SO"}, 6980{"SOUTH AFRICA", "ZA"}, 6981{"SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS", "GS"}, 6982{"SPAIN", "ES"}, 6983{"SRI LANKA", "LK"}, 6984{"SUDAN", "SD"}, 6985{"SURINAME", "SR"}, 6986{"SVALBARD AND JAN MAYEN","SJ"}, 6987{"SWAZILAND", "SZ"}, 6988{"SWEDEN", "SE"}, 6989{"SWITZERLAND", "CH"}, 6990{"SYRIAN ARAB REPUBLIC", "SY"}, 6991{"TAIWAN, PROVINCE OF CHINA", "TW"}, 6992{"TAJIKISTAN", "TJ"}, 6993{"TANZANIA, UNITED REPUBLIC OF", "TZ"}, 6994{"THAILAND", "TH"}, 6995{"TIMOR-LESTE", "TL"}, 6996{"TOGO", "TG"}, 6997{"TOKELAU", "TK"}, 6998{"TONGA", "TO"}, 6999{"TRINIDAD AND TOBAGO", "TT"}, 7000{"TRISTAN DA CUNHA", "TA"}, 7001{"TUNISIA", "TN"}, 7002{"TURKEY", "TR"}, 7003{"TURKMENISTAN", "TM"}, 7004{"TURKS AND CAICOS ISLANDS", "TC"}, 7005{"TUVALU", "TV"}, 7006{"UGANDA", "UG"}, 7007{"UKRAINE", "UA"}, 7008{"UNITED ARAB EMIRATES", "AE"}, 7009{"UNITED KINGDOM", "GB"}, 7010{"UNITED STATES", "US"}, 7011{"UNITED STATES MINOR OUTLYING ISLANDS","UM"}, 7012{"URUGUAY", "UY"}, 7013{"UZBEKISTAN", "UZ"}, 7014{"VANUATU", "VU"}, 7015{"VENEZUELA", "VE"}, 7016{"VIET NAM", "VN"}, 7017{"VIRGIN ISLANDS, BRITISH", "VG"}, 7018{"VIRGIN ISLANDS, U.S.", "VI"}, 7019{"WALLIS AND FUTUNA", "WF"}, 7020{"WESTERN SAHARA", "EH"}, 7021{"YEMEN", "YE"}, 7022{"YUGOSLAVIA", "YU"}, 7023{"ZAMBIA", "ZM"}, 7024{"ZIMBABWE", "ZW"}, 7025{"ALL", "ALL"}, 7026{"RADAR CHANNELS", "RDR"}, 7027{NULL, NULL} 7028}; 7029 7030