1/* 2 * Broadcom Home Gateway Reference Design 3 * Web Page Configuration Support Routines 4 * 5 * Copyright 2004, 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:33 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 35extern int conn_fd; 36#endif /* WEBS */ 37 38 39#include <typedefs.h> 40#include <proto/ethernet.h> 41#include <bcmnvram.h> 42#include <bcmutils.h> 43#include <shutils.h> 44#include <netconf.h> 45#include <nvparse.h> 46#include <wlutils.h> 47 48static char * rfctime(const time_t *timep); 49static char * reltime(unsigned int seconds); 50 51#define wan_prefix(unit, prefix) snprintf(prefix, sizeof(prefix), "wan%d_", unit) 52 53/* For Backup/Restore settings */ 54#define BACKUP_SETTING_FILENAME "s5config.dat" 55 56/* 57 * Country names and abbreviations from ISO 3166 58 */ 59typedef struct { 60 char *name; /* Long name */ 61 char *abbrev; /* Abbreviation */ 62} country_name_t; 63country_name_t country_names[]; /* At end of this file */ 64 65//char ibuf[WLC_IOCTL_MAXLEN]; 66//char ibuf2[WLC_IOCTL_MAXLEN]; 67static int ezc_error = 0; 68 69struct variable { 70 char *name; 71 char *longname; 72 void (*validate)(webs_t wp, char *value, struct variable *v); 73 char **argv; 74 int nullok; 75 int ezc_flags; 76}; 77 78struct variable variables[]; 79extern struct nvram_tuple router_defaults[]; 80 81#define ARGV(args...) ((char *[]) { args, NULL }) 82#define XSTR(s) STR(s) 83#define STR(s) #s 84 85enum { 86 NOTHING, 87 REBOOT, 88 RESTART, 89}; 90 91#define EZC_FLAGS_READ 0x0001 92#define EZC_FLAGS_WRITE 0x0002 93#define EZC_FLAGS_CRYPT 0x0004 94 95#define EZC_CRYPT_KEY "620A83A6960E48d1B05D49B0288A2C1F" 96 97#define EZC_SUCCESS 0 98#define EZC_ERR_NOT_ENABLED 1 99#define EZC_ERR_INVALID_STATE 2 100#define EZC_ERR_INVALID_DATA 3 101#ifndef NOUSB 102static const char * const apply_header = 103"<head>" 104"<title>Broadcom Home Gateway Reference Design: Apply</title>" 105"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" 106"<style type=\"text/css\">" 107"body { background: white; color: black; font-family: arial, sans-serif; font-size: 9pt }" 108".title { font-family: arial, sans-serif; font-size: 13pt; font-weight: bold }" 109".subtitle { font-family: arial, sans-serif; font-size: 11pt }" 110".label { color: #306498; font-family: arial, sans-serif; font-size: 7pt }" 111"</style>" 112"</head>" 113"<body>" 114"<p>" 115"<span class=\"title\">APPLY</span><br>" 116"<span class=\"subtitle\">This screen notifies you of any errors " 117"that were detected while changing the router's settings.</span>" 118"<form method=\"get\" action=\"apply.cgi\">" 119"<p>" 120; 121 122static const char * const apply_footer = 123"<p>" 124"<input type=\"button\" name=\"action\" value=\"Continue\" OnClick=\"document.location.href='%s';\">" 125"</form>" 126"<p class=\"label\">©2001-2004 Broadcom Corporation. All rights reserved.</p>" 127"</body>" 128; 129#endif 130 131#if defined(linux) 132 133#include <fcntl.h> 134#include <signal.h> 135#include <time.h> 136#include <sys/klog.h> 137#include <sys/wait.h> 138#include <sys/ioctl.h> 139#include <net/if.h> 140 141typedef u_int64_t u64; 142typedef u_int32_t u32; 143typedef u_int16_t u16; 144typedef u_int8_t u8; 145#include <linux/ethtool.h> 146#include <linux/sockios.h> 147#include <net/if_arp.h> 148 149#define sys_restart() kill(1, SIGHUP) 150#define sys_reboot() kill(1, SIGTERM) 151#define sys_stats(url) eval("stats", (url)) 152 153#ifndef WEBS 154 155#define MIN_BUF_SIZE 4096 156 157/* Upgrade from remote server or socket stream */ 158static int 159sys_upgrade(char *url, FILE *stream, int *total) 160{ 161 char upload_fifo[] = "/tmp/uploadXXXXXX"; 162 FILE *fifo = NULL; 163 char *write_argv[] = { "write", upload_fifo, "linux", NULL }; 164 pid_t pid; 165 char *buf = NULL; 166 int count, ret = 0; 167 long flags = -1; 168 int size = BUFSIZ; 169 170 if (url) 171 return eval("write", url, "linux"); 172 173 /* Feed write from a temporary FIFO */ 174 if (!mktemp(upload_fifo) || 175 mkfifo(upload_fifo, S_IRWXU) < 0|| 176 (ret = _eval(write_argv, NULL, 0, &pid)) || 177 !(fifo = fopen(upload_fifo, "w"))) { 178 if (!ret) 179 ret = errno; 180 goto err; 181 } 182 183 /* Set nonblock on the socket so we can timeout */ 184 /*if ((flags = fcntl(fileno(stream), F_GETFL)) < 0 || 185 fcntl(fileno(stream), F_SETFL, flags | O_NONBLOCK) < 0) {//*/ 186 if ((flags = fcntl(conn_fd, F_GETFL)) < 0 || 187 fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK) < 0) { 188 ret = errno; 189 goto err; 190 } 191 192 /* 193 * The buffer must be at least as big as what the stream file is 194 * using so that it can read all the data that has been buffered 195 * in the stream file. Otherwise it would be out of sync with fn 196 * select specially at the end of the data stream in which case 197 * the select tells there is no more data available but there in 198 * fact is data buffered in the stream file's buffer. Since no 199 * one has changed the default stream file's buffer size, let's 200 * use the constant BUFSIZ until someone changes it. 201 */ 202 if (size < MIN_BUF_SIZE) 203 size = MIN_BUF_SIZE; 204 if ((buf = malloc(size)) == NULL) { 205 ret = ENOMEM; 206 goto err; 207 } 208 209 /* Pipe the rest to the FIFO */ 210 cprintf("Upgrading"); 211 while (total && *total) { 212 //if (waitfor(fileno(stream), 5) <= 0) 213 if (waitfor(conn_fd, 5) <= 0) 214 break; 215 count = safe_fread(buf, 1, size, stream); 216 if (!count && (ferror(stream) || feof(stream))) 217 break; 218 *total -= count; 219 safe_fwrite(buf, 1, count, fifo); 220 cprintf("."); 221 } 222 fclose(fifo); 223 fifo = NULL; 224 225 /* Wait for write to terminate */ 226 waitpid(pid, &ret, 0); 227 cprintf("done\n"); 228 229 /* Reset nonblock on the socket */ 230 //if (fcntl(fileno(stream), F_SETFL, flags) < 0) { 231 if (fcntl(conn_fd, F_SETFL, flags) < 0) { 232 ret = errno; 233 goto err; 234 } 235 236 err: 237 if (buf) 238 free(buf); 239 if (fifo) 240 fclose(fifo); 241 unlink(upload_fifo); 242 return ret; 243} 244 245#endif 246 247int 248sys_send_signal(char *pidfile, int sig) 249{ 250 251 FILE *fp; 252 pid_t pid; 253 fp=fopen(pidfile,"r"); 254 if (fp!=NULL) 255 { 256 fscanf(fp, "%d", &pid); 257 kill(pid, sig); 258 fclose(fp); 259 return 0; 260 } 261 return 1; 262} 263 264void 265sys_refresh_lease(void) 266{ 267 char sigusr1[] = "-XX"; 268 269 /* Write out leases file */ 270 sprintf(sigusr1, "-%d", SIGUSR1); 271 eval("killall", sigusr1, "udhcpd"); 272} 273 274/* Dump firewall log */ 275static int 276ej_dumplog(int eid, webs_t wp, int argc, char_t **argv) 277{ 278 char buf[4096], *line, *next, *s; 279 int len, ret = 0; 280 281 time_t tm; 282 char *verdict, *src, *dst, *proto, *spt, *dpt; 283 284 if (klogctl(3, buf, 4096) < 0) { 285 websError(wp, 400, "Insufficient memory\n"); 286 return -1; 287 } 288 289 for (next = buf; (line = strsep(&next, "\n"));) { 290 if (!strncmp(line, "<4>DROP", 7)) 291 verdict = "denied"; 292 else if (!strncmp(line, "<4>ACCEPT", 9)) 293 verdict = "accepted"; 294 else 295 continue; 296 297 /* Parse into tokens */ 298 s = line; 299 len = strlen(s); 300 while (strsep(&s, " ")); 301 302 /* Initialize token values */ 303 time(&tm); 304 src = dst = proto = spt = dpt = "n/a"; 305 306 /* Set token values */ 307 for (s = line; s < &line[len] && *s; s += strlen(s) + 1) { 308 if (!strncmp(s, "TIME=", 5)) 309 tm = strtoul(&s[5], NULL, 10); 310 else if (!strncmp(s, "SRC=", 4)) 311 src = &s[4]; 312 else if (!strncmp(s, "DST=", 4)) 313 dst = &s[4]; 314 else if (!strncmp(s, "PROTO=", 6)) 315 proto = &s[6]; 316 else if (!strncmp(s, "SPT=", 4)) 317 spt = &s[4]; 318 else if (!strncmp(s, "DPT=", 4)) 319 dpt = &s[4]; 320 } 321 322 ret += websWrite(wp, "%s %s connection %s to %s:%s from %s:%s\n", 323 rfctime(&tm), proto, verdict, dst, dpt, src, spt); 324 ret += websWrite(wp, "<br>"); 325 } 326 327 return ret; 328} 329 330struct lease_t { 331 unsigned char chaddr[16]; 332 u_int32_t yiaddr; 333 u_int32_t expires; 334 char hostname[64]; 335}; 336 337/* Dump leases in <tr><td>hostname</td><td>MAC</td><td>IP</td><td>expires</td></tr> format */ 338int 339ej_lan_leases(int eid, webs_t wp, int argc, char_t **argv) 340{ 341 FILE *fp = NULL; 342 struct lease_t lease; 343 int i; 344 struct in_addr addr; 345 unsigned long expires = 0; 346 int ret = 0; 347 348 ret += websWrite(wp, "Host Name Mac Address IP Address Lease\n"); 349 350 /* Write out leases file */ 351 if (!(fp = fopen("/tmp/udhcpd-br0.leases", "r"))) 352 return ret; 353 354 while (fread(&lease, sizeof(lease), 1, fp)) { 355 /* Do not display reserved leases */ 356 if (ETHER_ISNULLADDR(lease.chaddr)) 357 continue; 358 359 //printf("lease: %s %d\n", lease.hostname, strlen(lease.hostname)); 360 ret += websWrite(wp, "%-16s", lease.hostname); 361 for (i = 0; i < 6; i++) { 362 ret += websWrite(wp, "%02X", lease.chaddr[i]); 363 if (i != 5) ret += websWrite(wp, ":"); 364 } 365 addr.s_addr = lease.yiaddr; 366 ret += websWrite(wp, " %-15s ", inet_ntoa(addr)); 367 expires = ntohl(lease.expires); 368 369 if (expires==0xffffffff) ret += websWrite(wp, "Manual\n"); 370 else if (!expires) ret += websWrite(wp, "Expired\n"); 371 else ret += websWrite(wp, "%s\n", reltime(expires)); 372 } 373 fclose(fp); 374 375#ifdef GUEST_ACCOUNT 376 if(nvram_invmatch("wl_guest_enable", "1")) return ret; 377 378 /* Write out leases file */ 379 if (!(fp = fopen("/tmp/udhcpd-br1.leases", "r"))) 380 return ret; 381 382 while (fread(&lease, sizeof(lease), 1, fp)) { 383 /* Do not display reserved leases */ 384 if (ETHER_ISNULLADDR(lease.chaddr)) 385 continue; 386 387 //printf("lease: %s %d\n", lease.hostname, strlen(lease.hostname)); 388 ret += websWrite(wp, "%-16s", lease.hostname); 389 for (i = 0; i < 6; i++) { 390 ret += websWrite(wp, "%02X", lease.chaddr[i]); 391 if (i != 5) ret += websWrite(wp, ":"); 392 } 393 addr.s_addr = lease.yiaddr; 394 ret += websWrite(wp, " %-15s ", inet_ntoa(addr)); 395 expires = ntohl(lease.expires); 396 397 if (expires==0xffffffff) ret += websWrite(wp, "Manual\n"); 398 else if (!expires) ret += websWrite(wp, "Expired\n"); 399 else ret += websWrite(wp, "%s\n", reltime(expires)); 400 } 401 fclose(fp); 402#endif 403 404 return ret; 405} 406 407/* Renew lease */ 408int 409sys_renew(void) 410{ 411 int unit; 412 char tmp[100]; 413 char *str; 414 int pid; 415 416 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 417 unit = 0; 418 419#ifdef REMOVE 420 snprintf(tmp, sizeof(tmp), "/var/run/udhcpc%d.pid", unit); 421 if ((str = file2str(tmp))) { 422 pid = atoi(str); 423 free(str); 424 return kill(pid, SIGUSR1); 425 } 426 return -1; 427#else 428 snprintf(tmp, sizeof(tmp), "wan_connect,%d", unit); 429 nvram_set("rc_service", tmp); 430 kill(1, SIGUSR1); 431 return 0; 432#endif 433} 434 435/* Release lease */ 436int 437sys_release(void) 438{ 439 int unit; 440 char tmp[100]; 441 char *str; 442 int pid; 443 444 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 445 unit = 0; 446 447#ifdef REMOVE 448 snprintf(tmp, sizeof(tmp), "/var/run/udhcpc%d.pid", unit); 449 if ((str = file2str(tmp))) { 450 pid = atoi(str); 451 free(str); 452 return kill(pid, SIGUSR2); 453 } 454 return -1; 455#else 456 snprintf(tmp, sizeof(tmp), "wan_disconnect,%d", unit); 457 nvram_set("rc_service", tmp); 458 kill(1, SIGUSR1); 459 return 0; 460#endif 461} 462 463#ifndef NOUSB 464static int 465wan_restore_mac(webs_t wp) 466{ 467 char tmp[50], tmp2[50], prefix[] = "wanXXXXXXXXXX_", *t2; 468 int unit, errf = -1; 469 char wan_ea[ETHER_ADDR_LEN]; 470 471 unit = atoi(websGetVar(wp, "wan_unit", NULL)); 472 if (unit >= 0) 473 { 474 strcpy(tmp2, nvram_safe_get("wan_ifname")); 475 if (!strncmp(tmp2, "eth", 3)) 476 { 477 sprintf(tmp, "et%dmacaddr", atoi(tmp2 + 3)); 478 t2 = nvram_safe_get(tmp); 479 if (t2 && t2[0] != 0) 480 { 481 ether_atoe(t2, wan_ea); 482 ether_etoa(wan_ea, tmp2); 483 wan_prefix(unit, prefix); 484 nvram_set("wan_hwaddr", tmp2); 485 nvram_set(strcat_r(prefix, "hwaddr", tmp), tmp2); 486 nvram_commit(); 487 errf = 0; 488 } 489 } 490 } 491 492 return errf; 493} 494 495#define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr) 496 497/* Return WAN link state */ 498static int 499ej_wan_link(int eid, webs_t wp, int argc, char_t **argv) 500{ 501 char *wan_ifname; 502 int s; 503 struct ifreq ifr; 504 struct ethtool_cmd ecmd; 505 FILE *fp; 506 int unit; 507 char tmp[100], prefix[] = "wanXXXXXXXXXX_"; 508 509 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 510 unit = 0; 511 wan_prefix(unit, prefix); 512 513 /* non-exist and disabled */ 514 if (nvram_match(strcat_r(prefix, "proto", tmp), "") || 515 nvram_match(strcat_r(prefix, "proto", tmp), "disabled")) { 516 return websWrite(wp, "N/A"); 517 } 518 /* PPPoE connection status */ 519 else if (nvram_match(strcat_r(prefix, "proto", tmp), "pppoe")) { 520 wan_ifname = nvram_safe_get(strcat_r(prefix, "pppoe_ifname", tmp)); 521 if ((fp = fopen(strcat_r("/tmp/ppp/link.", wan_ifname, tmp), "r"))) { 522 fclose(fp); 523 return websWrite(wp, "Connected"); 524 } else 525 return websWrite(wp, "Disconnected"); 526 } 527 /* Get real interface name */ 528 else 529 wan_ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 530 531 /* Open socket to kernel */ 532 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 533 return websWrite(wp, "N/A"); 534 535 /* Check for hardware link */ 536 strncpy(ifr.ifr_name, wan_ifname, IFNAMSIZ); 537 ifr.ifr_data = (void *) &ecmd; 538 ecmd.cmd = ETHTOOL_GSET; 539 if (ioctl(s, SIOCETHTOOL, &ifr) < 0) { 540 close(s); 541 return websWrite(wp, "Unknown"); 542 } 543 if (!ecmd.speed) { 544 close(s); 545 return websWrite(wp, "Disconnected"); 546 } 547 548 /* Check for valid IP address */ 549 strncpy(ifr.ifr_name, wan_ifname, IFNAMSIZ); 550 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { 551 close(s); 552 return websWrite(wp, "Connecting"); 553 } 554 555 /* Otherwise we are probably configured */ 556 close(s); 557 return websWrite(wp, "Connected"); 558} 559 560/* Display IP Address lease */ 561static int 562ej_wan_lease(int eid, webs_t wp, int argc, char_t **argv) 563{ 564 unsigned long expires = 0; 565 int ret = 0; 566 int unit; 567 char tmp[100], prefix[] = "wanXXXXXXXXXX_"; 568 569 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 570 unit = 0; 571 wan_prefix(unit, prefix); 572 573 if (nvram_match(strcat_r(prefix, "proto", tmp), "dhcp")) { 574 char *str; 575 time_t now; 576 577 snprintf(tmp, sizeof(tmp), "/tmp/udhcpc%d.expires", unit); 578 if ((str = file2str(tmp))) { 579 expires = atoi(str); 580 free(str); 581 } 582 time(&now); 583 if (expires <= now) 584 ret += websWrite(wp, "Expired"); 585 else 586 ret += websWrite(wp, "%s", reltime(expires - now)); 587 } else 588 ret += websWrite(wp, "N/A"); 589 590 return ret; 591} 592 593 594/* Return a list of wan interfaces (eth0/eth1/eth2/eth3) */ 595static int 596ej_wan_iflist(int eid, webs_t wp, int argc, char_t **argv) 597{ 598 char name[IFNAMSIZ], *next; 599 int ret = 0; 600 int unit; 601 char tmp[100], prefix[] = "wanXXXXXXXXXX_"; 602 char ea[64]; 603 int s; 604 struct ifreq ifr; 605 606 /* current unit # */ 607 if ((unit = atoi(nvram_safe_get("wan_unit"))) < 0) 608 unit = 0; 609 wan_prefix(unit, prefix); 610 611 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 612 return errno; 613 614 /* build wan interface name list */ 615 foreach(name, nvram_safe_get("wan_ifnames"), next) { 616 strncpy(ifr.ifr_name, name, IFNAMSIZ); 617 if (ioctl(s, SIOCGIFHWADDR, &ifr)) 618 continue; 619 ret += websWrite(wp, "<option value=\"%s\" %s>%s (%s)</option>", name, 620 nvram_match(strcat_r(prefix, "ifname", tmp), name) ? "selected" : "", 621 name, ether_etoa(ifr.ifr_hwaddr.sa_data, ea)); 622 } 623 624 close(s); 625 626 return ret; 627} 628 629#endif 630#endif 631 632 633#ifdef REMOVE 634static int 635ej_wl_parse_str(int eid, webs_t wp, int argc, char_t **argv) 636{ 637 char *var, *match, *next; 638 int unit, val = 0; 639 char tmp[100], prefix[] = "wlXXXXXXXXXX_"; 640 char *name; 641 char str[100]; 642 643 if (ejArgs(argc, argv, "%s %s", &var, &match) < 1) { 644 websError(wp, 400, "Insufficient args\n"); 645 return -1; 646 } 647 648 if ((unit = atoi(nvram_safe_get("wl_unit"))) < 0) 649 return -1; 650 651 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 652 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 653 654 if (wl_get_val(name, var, (void *)tmp, 100)) 655 return -1; 656 657 foreach(str, tmp, next) { 658 if (strncmp(str, match, sizeof(str)) == 0) { 659 val = 1; 660 break; 661 } 662 } 663 664 return websWrite(wp, "%u", val); 665} 666#endif 667 668int 669ej_wl_sta_status(int eid, webs_t wp, char *ifname) 670{ 671 int ret, i; 672 char bssid[32]; 673 char bssinfobuf[2000]; 674 wl_bss_info_t *info; 675 int val; 676 677 // Get bssid 678 ret=wl_ioctl(ifname, WLC_GET_BSSID, bssid, sizeof(bssid)); 679 //wl_scan_results(); 680 681 if (ret==0 && !(bssid[0]==0&&bssid[1]==0&&bssid[2]==0 682 &&bssid[3]==0&&bssid[4]==0&&bssid[5]==0)) 683 { 684 return(websWrite(wp, "Status : Connect to %s\n", nvram_safe_get("wl0_ssid"))); 685 } 686 return(websWrite(wp, "Status : Connecting to %s\n", nvram_safe_get("wl0_ssid"))); 687} 688 689 690int 691ej_wl_status(int eid, webs_t wp, int argc, char_t **argv) 692{ 693 int unit; 694 char tmp[100], prefix[] = "wlXXXXXXXXXX_"; 695 char *name; 696 struct maclist *auth, *assoc, *authorized; 697 int max_sta_count, maclist_size; 698 int i, j, ret, val; 699 channel_info_t ci; 700 701 if ((unit = atoi(nvram_safe_get("wl_unit"))) < 0) 702 return -1; 703 704 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 705 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 706 707 wl_ioctl(name, WLC_GET_RADIO, &val, sizeof(val)); 708 709 if (val==1) 710 { 711 ret+=websWrite(wp, "Radio is disabled\n"); 712 return 0; 713 } 714 715 wl_ioctl(name, WLC_GET_CHANNEL, &ci, sizeof(ci)); 716 717 718 if (nvram_match(strcat_r(prefix, "mode", tmp), "ap")) 719 { 720 if (nvram_match("wl_lazywds", "1") || 721 nvram_match("wl_wdsapply_x", "1")) 722 ret+=websWrite(wp, "Mode : Hybrid\n"); 723 else ret+=websWrite(wp, "Mode : AP Only\n"); 724 725 ret+=websWrite(wp, "Channel : %d\n", ci.target_channel); 726 727 } 728 else if (nvram_match(strcat_r(prefix, "mode", tmp), "wds")) 729 { 730 ret+=websWrite(wp, "Mode : WDS Only\n"); 731 ret+=websWrite(wp, "Channel : %d\n", ci.target_channel); 732 } 733 else if (nvram_match(strcat_r(prefix, "mode", tmp), "sta")) 734 { 735 ret+=websWrite(wp, "Mode : Stations\n"); 736 ret+=websWrite(wp, "Channel : %d\n", ci.target_channel); 737 ret+=ej_wl_sta_status(eid, wp, name); 738 return ret; 739 } 740 else if (nvram_match(strcat_r(prefix, "mode", tmp), "wet")) 741 { 742 ret+=websWrite(wp, "Mode : Ethernet Bridge\n"); 743 ret+=websWrite(wp, "Channel : %d\n", ci.target_channel); 744 ret+=ej_wl_sta_status(eid, wp, name); 745 return ret; 746 } 747 748 /* buffers and length */ 749 max_sta_count = 256; 750 maclist_size = sizeof(auth->count) + max_sta_count * sizeof(struct ether_addr); 751 752 auth = malloc(maclist_size); 753 assoc = malloc(maclist_size); 754 authorized = malloc(maclist_size); 755 756 if (!auth || !assoc || !authorized) 757 goto exit; 758 759 /* query wl for authenticated sta list */ 760 strcpy((char*)auth, "authe_sta_list"); 761 if (wl_ioctl(name, WLC_GET_VAR, auth, maclist_size)) 762 goto exit; 763 764 /* query wl for associated sta list */ 765 assoc->count = max_sta_count; 766 if (wl_ioctl(name, WLC_GET_ASSOCLIST, assoc, maclist_size)) 767 goto exit; 768 769 /* query wl for authorized sta list */ 770 strcpy((char*)authorized, "autho_sta_list"); 771 if (wl_ioctl(name, WLC_GET_VAR, authorized, maclist_size)) 772 goto exit; 773 774 775 websWrite(wp, "\n"); 776 websWrite(wp, "Stations List \n"); 777 websWrite(wp, "----------------------------------------\n"); 778 // 00:00:00:00:00:00 associated authorized 779 780 /* build authenticated/associated/authorized sta list */ 781 for (i = 0; i < auth->count; i ++) { 782 char ea[ETHER_ADDR_STR_LEN]; 783 784 websWrite(wp, "%s ", ether_etoa((void *)&auth->ea[i], ea)); 785 786 for (j = 0; j < assoc->count; j ++) { 787 if (!bcmp((void *)&auth->ea[i], (void *)&assoc->ea[j], ETHER_ADDR_LEN)) { 788 websWrite(wp, " associated"); 789 break; 790 } 791 } 792 793 for (j = 0; j < authorized->count; j ++) { 794 if (!bcmp((void *)&auth->ea[i], (void *)&authorized->ea[j], ETHER_ADDR_LEN)) { 795 websWrite(wp, " authorized"); 796 break; 797 } 798 } 799 websWrite(wp, "\n"); 800 } 801 802 /* error/exit */ 803exit: 804 if (auth) free(auth); 805 if (assoc) free(assoc); 806 if (authorized) free(authorized); 807 808 return 0; 809} 810 811/* Dump NAT table <tr><td>destination</td><td>MAC</td><td>IP</td><td>expires</td></tr> format */ 812int 813ej_nat_table(int eid, webs_t wp, int argc, char_t **argv) 814{ 815 int needlen = 0, listlen, i, ret; 816 netconf_nat_t *nat_list = 0; 817 netconf_nat_t **plist, *cur; 818 char line[256], tstr[32]; 819 820 ret += websWrite(wp, "Destination Proto. Port Range Redirect to\n"); 821 822 netconf_get_nat(NULL, &needlen); 823 824 if (needlen > 0) 825 { 826 827 nat_list = (netconf_nat_t *) malloc(needlen); 828 if (nat_list) { 829 memset(nat_list, 0, needlen); 830 listlen = needlen; 831 if (netconf_get_nat(nat_list, &listlen) == 0 && needlen == listlen) { 832 listlen = needlen/sizeof(netconf_nat_t); 833 834 for(i=0;i<listlen;i++) 835 { 836 //printf("%d %d %d\n", nat_list[i].target, 837 // nat_list[i].match.ipproto, 838 // nat_list[i].match.dst.ipaddr.s_addr); 839 if (nat_list[i].target==NETCONF_DNAT) 840 { 841 if (nat_list[i].match.dst.ipaddr.s_addr==0) 842 { 843 sprintf(line, "%-15s", "all"); 844 } 845 else 846 { 847 sprintf(line, "%-15s", inet_ntoa(nat_list[i].match.dst.ipaddr)); 848 } 849 850 851 if (ntohs(nat_list[i].match.dst.ports[0])==0) 852 sprintf(line, "%s %-7s", line, "ALL"); 853 else if (nat_list[i].match.ipproto==IPPROTO_TCP) 854 sprintf(line, "%s %-7s", line, "TCP"); 855 else sprintf(line, "%s %-7s", line, "UDP"); 856 857 if (nat_list[i].match.dst.ports[0] == nat_list[i].match.dst.ports[1]) 858 { 859 if (ntohs(nat_list[i].match.dst.ports[0])==0) 860 sprintf(line, "%s %-11s", line, "ALL"); 861 else 862 sprintf(line, "%s %-11d", line, ntohs(nat_list[i].match.dst.ports[0])); 863 } 864 else 865 { 866 sprintf(tstr, "%d:%d", ntohs(nat_list[i].match.dst.ports[0]), 867ntohs(nat_list[i].match.dst.ports[1])); 868 sprintf(line, "%s %-11s", line, tstr); 869 } 870 sprintf(line, "%s %s\n", line, inet_ntoa(nat_list[i].ipaddr)); 871 ret += websWrite(wp, line); 872 873 } 874 } 875 } 876 free(nat_list); 877 } 878 } 879 return 0; 880} 881 882int 883ej_route_table(int eid, webs_t wp, int argc, char_t **argv) 884{ 885 char buff[256]; 886 int nl = 0 ; 887 struct in_addr dest; 888 struct in_addr gw; 889 struct in_addr mask; 890 int flgs, ref, use, metric, ret; 891 char flags[4]; 892 unsigned long int d,g,m; 893 char sdest[16], sgw[16]; 894 FILE *fp; 895 896 ret += websWrite(wp, "Destination Gateway Genmask Flags Metric Ref Use Iface\n"); 897 898 if (!(fp = fopen("/proc/net/route", "r"))) return 0; 899 900 while(fgets(buff, sizeof(buff), fp) != NULL ) 901 { 902 if(nl) 903 { 904 int ifl = 0; 905 while(buff[ifl]!=' ' && buff[ifl]!='\t' && buff[ifl]!='\0') 906 ifl++; 907 buff[ifl]=0; /* interface */ 908 if(sscanf(buff+ifl+1, "%lx%lx%d%d%d%d%lx", 909 &d, &g, &flgs, &ref, &use, &metric, &m)!=7) { 910 //error_msg_and_die( "Unsuported kernel route format\n"); 911 //continue; 912 } 913 914 ifl = 0; /* parse flags */ 915 if(flgs&1) 916 flags[ifl++]='U'; 917 if(flgs&2) 918 flags[ifl++]='G'; 919 if(flgs&4) 920 flags[ifl++]='H'; 921 flags[ifl]=0; 922 dest.s_addr = d; 923 gw.s_addr = g; 924 mask.s_addr = m; 925 strcpy(sdest, (dest.s_addr==0 ? "default" : 926 inet_ntoa(dest))); 927 strcpy(sgw, (gw.s_addr==0 ? "*" : 928 inet_ntoa(gw))); 929 if(nvram_match("wan_proto","pppoe") && (strstr(buff, "eth0"))) 930 continue; 931 if (strstr(buff, "br0") || strstr(buff, "wl0")) 932 { 933 ret += websWrite(wp, "%-16s%-16s%-16s%-6s%-6d %-2d %7d LAN\n", 934 sdest, sgw, 935 inet_ntoa(mask), 936 flags, metric, ref, use); 937 } 938 else if(!strstr(buff, "lo")) 939 { 940 ret += websWrite(wp, "%-16s%-16s%-16s%-6s%-6d %-2d %7d WAN\n", 941 sdest, sgw, 942 inet_ntoa(mask), 943 flags, metric, ref, use); 944 } 945 } 946 nl++; 947 } 948 fclose(fp); 949 950 return 0; 951} 952