1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/* 18 * ASUS Home Gateway Reference Design 19 * Web Page Configuration Support Routines 20 * 21 * Copyright 2004, ASUSTeK Inc. 22 * All Rights Reserved. 23 * 24 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 25 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 26 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 27 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 28 */ 29 30#ifdef WEBS 31#include <webs.h> 32#include <uemf.h> 33#include <ej.h> 34#else /* !WEBS */ 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38#include <ctype.h> 39#include <errno.h> 40#include <unistd.h> 41#include <limits.h> 42#include <sys/types.h> 43#include <sys/stat.h> 44#include <sys/socket.h> 45#include <netinet/in.h> 46#include <arpa/inet.h> 47#include <assert.h> 48#include <httpd.h> 49#endif /* WEBS */ 50#include <typedefs.h> 51#include <bcmnvram.h> 52#include <bcmutils.h> 53#include <shutils.h> 54#include <ralink.h> 55#include <iwlib.h> 56#include <stapriv.h> 57#include <ethutils.h> 58#include <shared.h> 59#include <sys/mman.h> 60#ifndef O_BINARY 61#define O_BINARY 0 62#endif 63#ifndef MAP_FAILED 64#define MAP_FAILED (-1) 65#endif 66 67#define wan_prefix(unit, prefix) snprintf(prefix, sizeof(prefix), "wan%d_", unit) 68//static char * rfctime(const time_t *timep); 69//static char * reltime(unsigned int seconds); 70void reltime(unsigned int seconds, char *buf); 71static int wl_status(int eid, webs_t wp, int argc, char_t **argv, int unit); 72 73#include <fcntl.h> 74#include <signal.h> 75#include <time.h> 76#include <sys/klog.h> 77#include <sys/wait.h> 78#include <sys/ioctl.h> 79#include <net/if.h> 80#include <linux/sockios.h> 81#include <net/if_arp.h> 82 83#include <dirent.h> 84 85 86/************************ CONSTANTS & MACROS ************************/ 87 88/* 89 * Constants fof WE-9->15 90 */ 91#define IW15_MAX_FREQUENCIES 16 92#define IW15_MAX_BITRATES 8 93#define IW15_MAX_TXPOWER 8 94#define IW15_MAX_ENCODING_SIZES 8 95#define IW15_MAX_SPY 8 96#define IW15_MAX_AP 8 97 98/****************************** TYPES ******************************/ 99 100/* 101 * Struct iw_range up to WE-15 102 */ 103struct iw15_range 104{ 105 __u32 throughput; 106 __u32 min_nwid; 107 __u32 max_nwid; 108 __u16 num_channels; 109 __u8 num_frequency; 110 struct iw_freq freq[IW15_MAX_FREQUENCIES]; 111 __s32 sensitivity; 112 struct iw_quality max_qual; 113 __u8 num_bitrates; 114 __s32 bitrate[IW15_MAX_BITRATES]; 115 __s32 min_rts; 116 __s32 max_rts; 117 __s32 min_frag; 118 __s32 max_frag; 119 __s32 min_pmp; 120 __s32 max_pmp; 121 __s32 min_pmt; 122 __s32 max_pmt; 123 __u16 pmp_flags; 124 __u16 pmt_flags; 125 __u16 pm_capa; 126 __u16 encoding_size[IW15_MAX_ENCODING_SIZES]; 127 __u8 num_encoding_sizes; 128 __u8 max_encoding_tokens; 129 __u16 txpower_capa; 130 __u8 num_txpower; 131 __s32 txpower[IW15_MAX_TXPOWER]; 132 __u8 we_version_compiled; 133 __u8 we_version_source; 134 __u16 retry_capa; 135 __u16 retry_flags; 136 __u16 r_time_flags; 137 __s32 min_retry; 138 __s32 max_retry; 139 __s32 min_r_time; 140 __s32 max_r_time; 141 struct iw_quality avg_qual; 142}; 143 144/* 145 * Union for all the versions of iwrange. 146 * Fortunately, I mostly only add fields at the end, and big-bang 147 * reorganisations are few. 148 */ 149union iw_range_raw 150{ 151 struct iw15_range range15; /* WE 9->15 */ 152 struct iw_range range; /* WE 16->current */ 153}; 154 155/* 156 * Offsets in iw_range struct 157 */ 158#define iwr15_off(f) ( ((char *) &(((struct iw15_range *) NULL)->f)) - \ 159 (char *) NULL) 160#define iwr_off(f) ( ((char *) &(((struct iw_range *) NULL)->f)) - \ 161 (char *) NULL) 162 163/* Disable runtime version warning in ralink_get_range_info() */ 164int iw_ignore_version_sp = 0; 165 166/*------------------------------------------------------------------*/ 167/* 168 * Get the range information out of the driver 169 */ 170int 171ralink_get_range_info(iwrange * range, char* buffer, int length) 172{ 173 union iw_range_raw * range_raw; 174 175 /* Point to the buffer */ 176 range_raw = (union iw_range_raw *) buffer; 177 178 /* For new versions, we can check the version directly, for old versions 179 * we use magic. 300 bytes is a also magic number, don't touch... */ 180 if (length < 300) 181 { 182 /* That's v10 or earlier. Ouch ! Let's make a guess...*/ 183 range_raw->range.we_version_compiled = 9; 184 } 185 186 /* Check how it needs to be processed */ 187 if (range_raw->range.we_version_compiled > 15) 188 { 189 /* This is our native format, that's easy... */ 190 /* Copy stuff at the right place, ignore extra */ 191 memcpy((char *) range, buffer, sizeof(iwrange)); 192 } 193 else 194 { 195 /* Zero unknown fields */ 196 bzero((char *) range, sizeof(struct iw_range)); 197 198 /* Initial part unmoved */ 199 memcpy((char *) range, 200 buffer, 201 iwr15_off(num_channels)); 202 /* Frequencies pushed futher down towards the end */ 203 memcpy((char *) range + iwr_off(num_channels), 204 buffer + iwr15_off(num_channels), 205 iwr15_off(sensitivity) - iwr15_off(num_channels)); 206 /* This one moved up */ 207 memcpy((char *) range + iwr_off(sensitivity), 208 buffer + iwr15_off(sensitivity), 209 iwr15_off(num_bitrates) - iwr15_off(sensitivity)); 210 /* This one goes after avg_qual */ 211 memcpy((char *) range + iwr_off(num_bitrates), 212 buffer + iwr15_off(num_bitrates), 213 iwr15_off(min_rts) - iwr15_off(num_bitrates)); 214 /* Number of bitrates has changed, put it after */ 215 memcpy((char *) range + iwr_off(min_rts), 216 buffer + iwr15_off(min_rts), 217 iwr15_off(txpower_capa) - iwr15_off(min_rts)); 218 /* Added encoding_login_index, put it after */ 219 memcpy((char *) range + iwr_off(txpower_capa), 220 buffer + iwr15_off(txpower_capa), 221 iwr15_off(txpower) - iwr15_off(txpower_capa)); 222 /* Hum... That's an unexpected glitch. Bummer. */ 223 memcpy((char *) range + iwr_off(txpower), 224 buffer + iwr15_off(txpower), 225 iwr15_off(avg_qual) - iwr15_off(txpower)); 226 /* Avg qual moved up next to max_qual */ 227 memcpy((char *) range + iwr_off(avg_qual), 228 buffer + iwr15_off(avg_qual), 229 sizeof(struct iw_quality)); 230 } 231 232 /* We are now checking much less than we used to do, because we can 233 * accomodate more WE version. But, there are still cases where things 234 * will break... */ 235 if (!iw_ignore_version_sp) 236 { 237 /* We don't like very old version (unfortunately kernel 2.2.X) */ 238 if (range->we_version_compiled <= 10) 239 { 240 fprintf(stderr, "Warning: Driver for device %s has been compiled with an ancient version\n", "raxx"); 241 fprintf(stderr, "of Wireless Extension, while this program support version 11 and later.\n"); 242 fprintf(stderr, "Some things may be broken...\n\n"); 243 } 244 245 /* We don't like future versions of WE, because we can't cope with 246 * the unknown */ 247 if (range->we_version_compiled > WE_MAX_VERSION) 248 { 249 fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", "raxx", range->we_version_compiled); 250 fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_VERSION); 251 fprintf(stderr, "Some things may be broken...\n\n"); 252 } 253 254 /* Driver version verification */ 255 if ((range->we_version_compiled > 10) && 256 (range->we_version_compiled < range->we_version_source)) 257 { 258 fprintf(stderr, "Warning: Driver for device %s recommend version %d of Wireless Extension,\n", "raxx", range->we_version_source); 259 fprintf(stderr, "but has been compiled with version %d, therefore some driver features\n", range->we_version_compiled); 260 fprintf(stderr, "may not be available...\n\n"); 261 } 262 /* Note : we are only trying to catch compile difference, not source. 263 * If the driver source has not been updated to the latest, it doesn't 264 * matter because the new fields are set to zero */ 265 } 266 267 /* Don't complain twice. 268 * In theory, the test apply to each individual driver, but usually 269 * all drivers are compiled from the same kernel. */ 270 iw_ignore_version_sp = 1; 271 272 return (0); 273} 274 275 276char* GetBW(int BW) 277{ 278 switch(BW) 279 { 280 case BW_10: 281 return "10M"; 282 283 case BW_20: 284 return "20M"; 285 286 case BW_40: 287 return "40M"; 288 289#if defined(RTAC52U) || defined(RTAC51U) || defined(RTN54U) || defined(RTAC1200HP) || defined(RTAC54U) 290 case BW_80: 291 return "80M"; 292#endif 293 294 default: 295 return "N/A"; 296 } 297} 298 299char* GetPhyMode(int Mode) 300{ 301 switch(Mode) 302 { 303 case MODE_CCK: 304 return "CCK"; 305 306 case MODE_OFDM: 307 return "OFDM"; 308 case MODE_HTMIX: 309 return "HTMIX"; 310 311 case MODE_HTGREENFIELD: 312 return "GREEN"; 313 314#if defined(RTAC52U) || defined(RTAC51U) || defined(RTN54U) || defined(RTAC1200HP) || defined(RTAC54U) 315 case MODE_VHT: 316 return "VHT"; 317#endif 318 319 default: 320 return "N/A"; 321 } 322} 323 324int MCSMappingRateTable[] = 325 {2, 4, 11, 22, // CCK 326 12, 18, 24, 36, 48, 72, 96, 108, // OFDM 327 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, // 20MHz, 800ns GI, MCS: 0 ~ 15 328 39, 78, 117, 156, 234, 312, 351, 390, // 20MHz, 800ns GI, MCS: 16 ~ 23 329 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, // 40MHz, 800ns GI, MCS: 0 ~ 15 330 81, 162, 243, 324, 486, 648, 729, 810, // 40MHz, 800ns GI, MCS: 16 ~ 23 331 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, // 20MHz, 400ns GI, MCS: 0 ~ 15 332 43, 87, 130, 173, 260, 317, 390, 433, // 20MHz, 400ns GI, MCS: 16 ~ 23 333 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15 334 90, 180, 270, 360, 540, 720, 810, 900, 335 13, 26, 39, 52, 78, 104, 117, 130, 156, /* 11ac: 20Mhz, 800ns GI, MCS: 0~8 */ 336 27, 54, 81, 108, 162, 216, 243, 270, 324, 360, /*11ac: 40Mhz, 800ns GI, MCS: 0~9 */ 337 59, 117, 176, 234, 351, 468, 527, 585, 702, 780, /*11ac: 80Mhz, 800ns GI, MCS: 0~9 */ 338 14, 29, 43, 57, 87, 115, 130, 144, 173, /* 11ac: 20Mhz, 400ns GI, MCS: 0~8 */ 339 30, 60, 90, 120, 180, 240, 270, 300, 360, 400, /*11ac: 40Mhz, 400ns GI, MCS: 0~9 */ 340 65, 130, 195, 260, 390, 520, 585, 650, 780, 867 /*11ac: 80Mhz, 400ns GI, MCS: 0~9 */ 341 }; 342 343 344#define FN_GETRATE(_fn_, _st_) \ 345_fn_(_st_ HTSetting) \ 346{ \ 347 int rate_count = sizeof(MCSMappingRateTable)/sizeof(int); \ 348 int rate_index = 0; \ 349 \ 350 if (HTSetting.field.MODE >= MODE_VHT) \ 351 { \ 352 if (HTSetting.field.BW == BW_20) { \ 353 rate_index = 108 + \ 354 ((unsigned char)HTSetting.field.ShortGI * 29) + \ 355 ((unsigned char)HTSetting.field.MCS); \ 356 } \ 357 else if (HTSetting.field.BW == BW_40) { \ 358 rate_index = 117 + \ 359 ((unsigned char)HTSetting.field.ShortGI * 29) + \ 360 ((unsigned char)HTSetting.field.MCS); \ 361 } \ 362 else if (HTSetting.field.BW == BW_80) { \ 363 rate_index = 127 + \ 364 ((unsigned char)HTSetting.field.ShortGI * 29) + \ 365 ((unsigned char)HTSetting.field.MCS); \ 366 } \ 367 } \ 368 else \ 369 if (HTSetting.field.MODE >= MODE_HTMIX) \ 370 { \ 371 rate_index = 12 + ((unsigned char)HTSetting.field.BW *24) + ((unsigned char)HTSetting.field.ShortGI *48) + ((unsigned char)HTSetting.field.MCS); \ 372 } \ 373 else \ 374 if (HTSetting.field.MODE == MODE_OFDM) \ 375 rate_index = (unsigned char)(HTSetting.field.MCS) + 4; \ 376 else if (HTSetting.field.MODE == MODE_CCK) \ 377 rate_index = (unsigned char)(HTSetting.field.MCS); \ 378 \ 379 if (rate_index < 0) \ 380 rate_index = 0; \ 381 \ 382 if (rate_index >= rate_count) \ 383 rate_index = rate_count-1; \ 384 \ 385 return (MCSMappingRateTable[rate_index] * 5)/10; \ 386} 387 388#if defined(RTCONFIG_HAS_5G) 389int FN_GETRATE(getRate, MACHTTRANSMIT_SETTING_for_5G) //getRate (MACHTTRANSMIT_SETTING_for_5G) 390#endif /* RTCONFIG_HAS_5G */ 391int FN_GETRATE(getRate_2g, MACHTTRANSMIT_SETTING_for_2G) //getRate_2g(MACHTTRANSMIT_SETTING_for_2G) 392 393 394 395int 396ej_wl_status(int eid, webs_t wp, int argc, char_t **argv, int unit) 397{ 398 int retval = 0; 399 int ii = 0; 400 char word[256], *next; 401 402 foreach (word, nvram_safe_get("wl_ifnames"), next) { 403 retval += wl_status(eid, wp, argc, argv, ii); 404 retval += websWrite(wp, "\n"); 405 406 ii++; 407 } 408 409 return retval; 410} 411 412int 413ej_wl_status_2g(int eid, webs_t wp, int argc, char_t **argv) 414{ 415 return ej_wl_status(eid, wp, argc, argv, 0); 416} 417 418static int 419wl_status(int eid, webs_t wp, int argc, char_t **argv, int unit) 420{ 421 int ret = 0; 422 int channel; 423 struct iw_range range; 424 double freq; 425 struct iwreq wrq0; 426 struct iwreq wrq1; 427 struct iwreq wrq2; 428 struct iwreq wrq3; 429 unsigned long phy_mode; 430 char tmp[128], prefix[] = "wlXXXXXXXXXX_", *ifname; 431 int wl_mode_x; 432 int r; 433 434 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 435 ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 436 437#if 0 438 if (nvram_match(strcat_r(prefix, "radio", tmp), "0")) 439 { 440 ret+=websWrite(wp, "%s radio is disabled\n", 441 nvram_match(strcat_r(prefix, "nband", tmp), "1") ? "5 GHz" : "2.4 GHz"); 442 return ret; 443 } 444#else 445 if (!get_radio_status(ifname)) 446 { 447#if defined(BAND_2G_ONLY) 448 ret+=websWrite(wp, "2.4 GHz radio is disabled\n"); 449#else 450 ret+=websWrite(wp, "%s radio is disabled\n", 451 nvram_match(strcat_r(prefix, "nband", tmp), "1") ? "5 GHz" : "2.4 GHz"); 452#endif 453 return ret; 454 } 455#endif 456 457 if (wl_ioctl(ifname, SIOCGIWAP, &wrq0) < 0) 458 { 459#if defined(BAND_2G_ONLY) 460 ret+=websWrite(wp, "2.4 GHz radio is disabled\n"); 461#else 462 ret+=websWrite(wp, "%s radio is disabled\n", 463 nvram_match(strcat_r(prefix, "nband", tmp), "1") ? "5 GHz" : "2.4 GHz"); 464#endif 465 return ret; 466 } 467 468 wrq0.u.ap_addr.sa_family = ARPHRD_ETHER; 469 ret+=websWrite(wp, "MAC address : %02X:%02X:%02X:%02X:%02X:%02X\n", 470 (unsigned char)wrq0.u.ap_addr.sa_data[0], 471 (unsigned char)wrq0.u.ap_addr.sa_data[1], 472 (unsigned char)wrq0.u.ap_addr.sa_data[2], 473 (unsigned char)wrq0.u.ap_addr.sa_data[3], 474 (unsigned char)wrq0.u.ap_addr.sa_data[4], 475 (unsigned char)wrq0.u.ap_addr.sa_data[5]); 476 477 if (wl_ioctl(ifname, SIOCGIWFREQ, &wrq1) < 0) 478 return ret; 479 480 char buffer[sizeof(iwrange) * 2]; 481 bzero(buffer, sizeof(buffer)); 482 wrq2.u.data.pointer = (caddr_t) buffer; 483 wrq2.u.data.length = sizeof(buffer); 484 wrq2.u.data.flags = 0; 485 486 if (wl_ioctl(ifname, SIOCGIWRANGE, &wrq2) < 0) 487 return ret; 488 489 if (ralink_get_range_info(&range, buffer, wrq2.u.data.length) < 0) 490 return ret; 491 492#if defined(RTN65U) 493 if (unit == 0 && get_model() == MODEL_RTN65U) 494 { 495 FILE *fp; 496 phy_mode = 0; 497 if((fp = fopen("/etc/Wireless/iNIC/iNIC_ap.dat", "r")) != NULL) 498 { 499 while(fgets(tmp, sizeof(tmp), fp) != NULL) 500 { 501 if(strncmp(tmp, "WirelessMode=", 13) == 0) 502 { 503 phy_mode = atoi(tmp + 13); 504 break; 505 } 506 } 507 fclose(fp); 508 } 509 } 510 else 511 { 512#endif /* RTN65U */ 513 bzero(buffer, sizeof(unsigned long)); 514 wrq2.u.data.length = sizeof(unsigned long); 515 wrq2.u.data.pointer = (caddr_t) buffer; 516 wrq2.u.data.flags = RT_OID_GET_PHY_MODE; 517 518 if (wl_ioctl(ifname, RT_PRIV_IOCTL, &wrq2) < 0) 519 return ret; 520 521 if(wrq2.u.mode == (__u32) buffer) //.u.mode is at the same location as u.data.pointer 522 { //new wifi driver 523 phy_mode = 0; 524 memcpy(&phy_mode, wrq2.u.data.pointer, wrq2.u.data.length); 525 } 526 else 527 phy_mode=wrq2.u.mode; 528#if defined(RTN65U) 529 } 530#endif /* RTN65U */ 531 532 freq = iw_freq2float(&(wrq1.u.freq)); 533 if (freq < KILO) 534 channel = (int) freq; 535 else 536 { 537 channel = iw_freq_to_channel(freq, &range); 538 if (channel < 0) 539 return ret; 540 } 541 542 wl_mode_x = nvram_get_int(strcat_r(prefix, "mode_x", tmp)); 543 if (wl_mode_x == 1) 544 ret+=websWrite(wp, "OP Mode : WDS Only\n"); 545 else if (wl_mode_x == 2) 546 ret+=websWrite(wp, "OP Mode : Hybrid\n"); 547 else 548 ret+=websWrite(wp, "OP Mode : AP\n"); 549 550#if defined(RTAC52U) || defined(RTAC51U) || defined(RTN54U) || defined(RTAC1200HP) || defined(RTAC54U) 551 if (unit == 1) 552 { 553 char *p = tmp; 554 if(phy_mode & WMODE_A) 555 p += sprintf(p, "/a"); 556 if(phy_mode & WMODE_B) 557 p += sprintf(p, "/b"); 558 if(phy_mode & WMODE_G) 559 p += sprintf(p, "/g"); 560 if(phy_mode & WMODE_GN) 561 p += sprintf(p, "/n"); //N in 2G 562 if(phy_mode & WMODE_AN) 563 p += sprintf(p, "/n"); //N in 5G 564 if(phy_mode & WMODE_AC) 565 p += sprintf(p, "/ac"); 566 if(p != tmp) 567 ret+=websWrite(wp, "Phy Mode : 11%s\n", tmp+1); // skip first '/' 568 } 569 else 570#endif 571 if (phy_mode==PHY_11BG_MIXED) 572 ret+=websWrite(wp, "Phy Mode : 11b/g\n"); 573 else if (phy_mode==PHY_11B) 574 ret+=websWrite(wp, "Phy Mode : 11b\n"); 575 else if (phy_mode==PHY_11A) 576 ret+=websWrite(wp, "Phy Mode : 11a\n"); 577 else if (phy_mode==PHY_11ABG_MIXED) 578 ret+=websWrite(wp, "Phy Mode : 11a/b/g\n"); 579 else if (phy_mode==PHY_11G) 580 ret+=websWrite(wp, "Phy Mode : 11g\n"); 581 else if (phy_mode==PHY_11ABGN_MIXED) 582 ret+=websWrite(wp, "Phy Mode : 11a/b/g/n\n"); 583 else if (phy_mode==PHY_11N) 584 ret+=websWrite(wp, "Phy Mode : 11n\n"); 585 else if (phy_mode==PHY_11GN_MIXED) 586 ret+=websWrite(wp, "Phy Mode : 11g/n\n"); 587 else if (phy_mode==PHY_11AN_MIXED) 588 ret+=websWrite(wp, "Phy Mode : 11a/n\n"); 589 else if (phy_mode==PHY_11BGN_MIXED) 590 ret+=websWrite(wp, "Phy Mode : 11b/g/n\n"); 591 else if (phy_mode==PHY_11AGN_MIXED) 592 ret+=websWrite(wp, "Phy Mode : 11a/g/n\n"); 593 594 ret+=websWrite(wp, "Channel : %d\n", channel); 595 596 char data[16384]; 597 memset(data, 0, sizeof(data)); 598 wrq3.u.data.pointer = data; 599 wrq3.u.data.length = sizeof(data); 600 wrq3.u.data.flags = 0; 601 602 if ((r = wl_ioctl(ifname, RTPRIV_IOCTL_GET_MAC_TABLE, &wrq3)) < 0) { 603 _dprintf("%s: Take MAC table from i/f %s fail! ret %d, errno %d (%s)\n", 604 __func__, r, errno, strerror(errno)); 605 return ret; 606 } 607 608 RT_802_11_MAC_TABLE_5G* mp =(RT_802_11_MAC_TABLE_5G*)wrq3.u.data.pointer; 609 RT_802_11_MAC_TABLE_2G* mp2=(RT_802_11_MAC_TABLE_2G*)wrq3.u.data.pointer; 610 int i; 611 612 ret+=websWrite(wp, "\nStations List \n"); 613 ret+=websWrite(wp, "----------------------------------------\n"); 614 ret+=websWrite(wp, "%-18s%-4s%-8s%-4s%-4s%-4s%-5s%-5s%-12s\n", 615 "MAC", "PSM", "PhyMode", "BW", "MCS", "SGI", "STBC", "Rate", "Connect Time"); 616 617#define SHOW_STA_INFO(_p,_i,_st, _gr) { \ 618 int hr, min, sec; \ 619 _st *Entry = ((_st *)(_p)) + _i; \ 620 hr = Entry->ConnectedTime/3600; \ 621 min = (Entry->ConnectedTime % 3600)/60; \ 622 sec = Entry->ConnectedTime - hr*3600 - min*60; \ 623 ret+=websWrite(wp, "%02X:%02X:%02X:%02X:%02X:%02X %s %-7s %s %3d %s %s %3dM %02d:%02d:%02d\n", \ 624 Entry->Addr[0], Entry->Addr[1], \ 625 Entry->Addr[2], Entry->Addr[3], \ 626 Entry->Addr[4], Entry->Addr[5], \ 627 Entry->Psm ? "Yes" : "NO ", \ 628 GetPhyMode(Entry->TxRate.field.MODE), \ 629 GetBW(Entry->TxRate.field.BW), \ 630 Entry->TxRate.field.MCS, \ 631 Entry->TxRate.field.ShortGI ? "Yes" : "NO ", \ 632 Entry->TxRate.field.STBC ? "Yes" : "NO ", \ 633 _gr(Entry->TxRate), \ 634 hr, min, sec \ 635 ); \ 636 } 637 638 if (!strcmp(ifname, WIF_2G)) { 639 for (i=0;i<mp->Num;i++) { 640 SHOW_STA_INFO(mp2->Entry, i, RT_802_11_MAC_ENTRY_for_2G, getRate_2g); 641 } 642 } 643#if defined(RTCONFIG_HAS_5G) 644 else { 645 for (i=0;i<mp->Num;i++) { 646 SHOW_STA_INFO(mp->Entry, i, RT_802_11_MAC_ENTRY_for_5G, getRate); 647 } 648 } 649#endif /* RTCONFIG_HAS_5G */ 650 651 return ret; 652} 653 654typedef struct PACKED _WSC_CONFIGURED_VALUE { 655 unsigned short WscConfigured; // 1 un-configured; 2 configured 656 unsigned char WscSsid[32 + 1]; 657 unsigned short WscAuthMode; // mandatory, 0x01: open, 0x02: wpa-psk, 0x04: shared, 0x08:wpa, 0x10: wpa2, 0x 658 unsigned short WscEncrypType; // 0x01: none, 0x02: wep, 0x04: tkip, 0x08: aes 659 unsigned char DefaultKeyIdx; 660 unsigned char WscWPAKey[64 + 1]; 661} WSC_CONFIGURED_VALUE; 662 663void getWPSAuthMode(WSC_CONFIGURED_VALUE *result, char *ret_str) 664{ 665 if (result->WscAuthMode & 0x1) 666 strcat(ret_str, "Open System"); 667 if (result->WscAuthMode & 0x2) 668 strcat(ret_str, "WPA-Personal"); 669 if (result->WscAuthMode & 0x4) 670 strcat(ret_str, "Shared Key"); 671 if (result->WscAuthMode & 0x8) 672 strcat(ret_str, "WPA-Enterprise"); 673 if (result->WscAuthMode & 0x10) 674 strcat(ret_str, "WPA2-Enterprise"); 675 if (result->WscAuthMode & 0x20) 676 strcat(ret_str, "WPA2-Personal"); 677} 678 679void getWPSEncrypType(WSC_CONFIGURED_VALUE *result, char *ret_str) 680{ 681 if (result->WscEncrypType & 0x1) 682 strcat(ret_str, "None"); 683 if (result->WscEncrypType & 0x2) 684 strcat(ret_str, "WEP"); 685 if (result->WscEncrypType & 0x4) 686 strcat(ret_str, "TKIP"); 687 if (result->WscEncrypType & 0x8) 688 strcat(ret_str, "AES"); 689} 690 691/* 692 * these definitions are from rt2860v2 driver include/wsc.h 693 */ 694char *getWscStatusStr(int status) 695{ 696 switch(status) { 697 case 0: 698 return "Not used"; 699 case 1: 700 return "Idle"; 701 case 2: 702#if 0 703 return "WPS Fail(Ignore this if Intel/Marvell registrar used)"; 704#else 705 return "Idle"; 706#endif 707 case 3: 708 return "Start WPS Process"; 709 case 4: 710 return "Received EAPOL-Start"; 711 case 5: 712 return "Sending EAP-Req(ID)"; 713 case 6: 714 return "Receive EAP-Rsp(ID)"; 715 case 7: 716 return "Receive EAP-Req with wrong WPS SMI Vendor Id"; 717 case 8: 718 return "Receive EAP-Req with wrong WPS Vendor Type"; 719 case 9: 720 return "Sending EAP-Req(WPS_START)"; 721 case 10: 722 return "Send M1"; 723 case 11: 724 return "Received M1"; 725 case 12: 726 return "Send M2"; 727 case 13: 728 return "Received M2"; 729 case 14: 730 return "Received M2D"; 731 case 15: 732 return "Send M3"; 733 case 16: 734 return "Received M3"; 735 case 17: 736 return "Send M4"; 737 case 18: 738 return "Received M4"; 739 case 19: 740 return "Send M5"; 741 case 20: 742 return "Received M5"; 743 case 21: 744 return "Send M6"; 745 case 22: 746 return "Received M6"; 747 case 23: 748 return "Send M7"; 749 case 24: 750 return "Received M7"; 751 case 25: 752 return "Send M8"; 753 case 26: 754 return "Received M8"; 755 case 27: 756 return "Processing EAP Response (ACK)"; 757 case 28: 758 return "Processing EAP Request (Done)"; 759 case 29: 760 return "Processing EAP Response (Done)"; 761 case 30: 762 return "Sending EAP-Fail"; 763 case 31: 764 return "WPS_ERROR_HASH_FAIL"; 765 case 32: 766 return "WPS_ERROR_HMAC_FAIL"; 767 case 33: 768 return "WPS_ERROR_DEV_PWD_AUTH_FAIL"; 769 case 34: 770// return "Configured"; 771 return "Success"; 772 case 35: 773 return "SCAN AP"; 774 case 36: 775 return "EAPOL START SENT"; 776 case 37: 777 return "WPS_EAP_RSP_DONE_SENT"; 778 case 38: 779 return "WAIT PINCODE"; 780 case 39: 781 return "WSC_START_ASSOC"; 782 case 0x101: 783 return "PBC:TOO MANY AP"; 784 case 0x102: 785 return "PBC:NO AP"; 786 case 0x103: 787 return "EAP_FAIL_RECEIVED"; 788 case 0x104: 789 return "EAP_NONCE_MISMATCH"; 790 case 0x105: 791 return "EAP_INVALID_DATA"; 792 case 0x106: 793 return "PASSWORD_MISMATCH"; 794 case 0x107: 795 return "EAP_REQ_WRONG_SMI"; 796 case 0x108: 797 return "EAP_REQ_WRONG_VENDOR_TYPE"; 798 case 0x109: 799 return "PBC_SESSION_OVERLAP"; 800 default: 801 return "Unknown"; 802 } 803} 804 805int getWscStatus(int unit) 806{ 807 int data = 0; 808 struct iwreq wrq; 809 char tmp[128], prefix[] = "wlXXXXXXXXXX_"; 810 811 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 812 813 wrq.u.data.length = sizeof(data); 814 wrq.u.data.pointer = (caddr_t) &data; 815 wrq.u.data.flags = RT_OID_WSC_QUERY_STATUS; 816 817 if (wl_ioctl(nvram_safe_get(strcat_r(prefix, "ifname", tmp)), RT_PRIV_IOCTL, &wrq) < 0) 818 fprintf(stderr, "errors in getting WSC status\n"); 819 820 return data; 821} 822 823unsigned int getAPPIN(int unit) 824{ 825 unsigned int data = 0; 826 struct iwreq wrq; 827 char tmp[128], prefix[] = "wlXXXXXXXXXX_"; 828 829 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 830 831 wrq.u.data.length = sizeof(data); 832 wrq.u.data.pointer = (caddr_t) &data; 833 wrq.u.data.flags = RT_OID_WSC_PIN_CODE; 834 835 if (wl_ioctl(nvram_safe_get(strcat_r(prefix, "ifname", tmp)), RT_PRIV_IOCTL, &wrq) < 0) 836 fprintf(stderr, "errors in getting AP PIN\n"); 837 838 return data; 839} 840 841int 842wl_wps_info(int eid, webs_t wp, int argc, char_t **argv, int unit) 843{ 844 int i, j = -1, u = unit; 845 char tmpstr[128], tmpstr2[256]; 846 WSC_CONFIGURED_VALUE result; 847 int retval=0; 848 struct iwreq wrq; 849 char tmp[128], prefix[] = "wlXXXXXXXXXX_"; 850 char *wps_sta_pin; 851 char tag1[] = "<wps_infoXXXXXX>", tag2[] = "</wps_infoXXXXXX>"; 852 853#if defined(RTCONFIG_WPSMULTIBAND) 854 for (j = -1; j < MAX_NR_WL_IF; ++j) { 855#endif 856 switch (j) { 857 case 0: /* fall through */ 858 case 1: 859 u = j; 860 sprintf(tag1, "<wps_info%d>", j); 861 sprintf(tag2, "</wps_info%d>", j); 862 break; 863 case -1: /* fall through */ 864 default: 865 u = unit; 866 strcpy(tag1, "<wps_info>"); 867 strcpy(tag2, "</wps_info>"); 868 } 869 870 snprintf(prefix, sizeof(prefix), "wl%d_", u); 871 wrq.u.data.length = sizeof(WSC_CONFIGURED_VALUE); 872 wrq.u.data.pointer = (caddr_t) &result; 873 wrq.u.data.flags = 0; 874 strcpy((char *)&result, "get_wsc_profile"); 875 876#if defined(RTCONFIG_WPSMULTIBAND) 877 if (!nvram_get(strcat_r(prefix, "ifname", tmp))) 878 continue; 879#endif 880 881 if (wl_ioctl(nvram_safe_get(strcat_r(prefix, "ifname", tmp)), RTPRIV_IOCTL_WSC_PROFILE, &wrq) < 0) { 882 fprintf(stderr, "errors in getting WSC profile\n"); 883 return 0; 884 } 885 886 if (j == -1) 887 retval += websWrite(wp, "<wps>\n"); 888 889 //0. WSC Status 890 retval += websWrite(wp, "%s%s%s\n", tag1, getWscStatusStr(getWscStatus(u)), tag2); 891 892 //1. WPSConfigured 893 if (result.WscConfigured==2) 894 retval += websWrite(wp, "%s%s%s\n", tag1, "Yes", tag2); 895 else 896 retval += websWrite(wp, "%s%s%s\n", tag1, "No", tag2); 897 898 //2. WPSSSID 899 memset(tmpstr, 0, sizeof(tmpstr)); 900 char_to_ascii(tmpstr, result.WscSsid); 901 retval += websWrite(wp, "%s%s%s\n", tag1, tmpstr, tag2); 902 903 //3. WPSAuthMode 904 memset(tmpstr, 0, sizeof(tmpstr)); 905 getWPSAuthMode(&result, tmpstr); 906 retval += websWrite(wp, "%s%s%s\n", tag1, tmpstr, tag2); 907 908 //4. EncrypType 909 memset(tmpstr, 0, sizeof(tmpstr)); 910 getWPSEncrypType(&result, tmpstr); 911 retval += websWrite(wp, "%s%s%s\n", tag1, tmpstr, tag2); 912 913 //5. DefaultKeyIdx 914 memset(tmpstr, 0, sizeof(tmpstr)); 915 sprintf(tmpstr, "%d", result.DefaultKeyIdx); 916 retval += websWrite(wp, "%s%s%s\n", tag1, tmpstr, tag2); 917 918 //6. WPAKey 919 memset(tmpstr, 0, sizeof(tmpstr)); 920 for (i=0; i<64; i++) // WPA key default length is 64 (defined & hardcode in driver) 921 { 922 sprintf(tmpstr, "%s%c", tmpstr, result.WscWPAKey[i]); 923 } 924 if (!strlen(tmpstr)) 925 retval += websWrite(wp, "%sNone%s\n", tag1, tag2); 926 else 927 { 928 char_to_ascii(tmpstr2, tmpstr); 929 retval += websWrite(wp, "%s%s%s\n", tag1, tmpstr2, tag2); 930 } 931 932 //7. AP PIN Code 933 retval += websWrite(wp, "%s%08d%s\n", tag1, getAPPIN(u), tag2); 934 935 //8. Saved WPAKey 936 if (!strlen(nvram_safe_get(strcat_r(prefix, "wpa_psk", tmp)))) 937 retval += websWrite(wp, "%s%s%s\n", tag1, "None", tag2); 938 else 939 { 940 char_to_ascii(tmpstr, nvram_safe_get(strcat_r(prefix, "wpa_psk", tmp))); 941 retval += websWrite(wp, "%s%s%s\n", tag1, tmpstr, tag2); 942 } 943 944 //9. WPS enable? 945 if (!strcmp(nvram_safe_get(strcat_r(prefix, "wps_mode", tmp)), "enabled")) 946 retval += websWrite(wp, "%s%s%s\n", tag1, "None", tag2); 947 else 948 retval += websWrite(wp, "%s%s%s\n", tag1, nvram_safe_get("wps_enable"), tag2); 949 950 //A. WPS mode 951 wps_sta_pin = nvram_safe_get("wps_sta_pin"); 952 if (strlen(wps_sta_pin) && strcmp(wps_sta_pin, "00000000")) 953 retval += websWrite(wp, "%s%s%s\n", tag1, "1", tag2); 954 else 955 retval += websWrite(wp, "%s%s%s\n", tag1, "2", tag2); 956 957 //B. current auth mode 958 if (!strlen(nvram_safe_get(strcat_r(prefix, "auth_mode_x", tmp)))) 959 retval += websWrite(wp, "%s%s%s\n", tag1, "None", tag2); 960 else 961 retval += websWrite(wp, "%s%s%s\n", tag1, nvram_safe_get(strcat_r(prefix, "auth_mode_x", tmp)), tag2); 962 963 //C. WPS band 964 retval += websWrite(wp, "%s%d%s\n", tag1, u, tag2); 965#if defined(RTCONFIG_WPSMULTIBAND) 966 } 967#endif 968 969 retval += websWrite(wp, "</wps>"); 970 971 return retval; 972} 973 974int 975ej_wps_info(int eid, webs_t wp, int argc, char_t **argv) 976{ 977 return wl_wps_info(eid, wp, argc, argv, 1); 978} 979 980int 981ej_wps_info_2g(int eid, webs_t wp, int argc, char_t **argv) 982{ 983 return wl_wps_info(eid, wp, argc, argv, 0); 984} 985 986// Wireless Client List /* Start --Alicia, 08.09.23 */ 987 988int ej_wl_sta_list_2g(int eid, webs_t wp, int argc, char_t **argv) 989{ 990 struct iwreq wrq; 991 int i, firstRow; 992 char data[16384]; 993 char mac[ETHER_ADDR_STR_LEN]; 994 RT_802_11_MAC_TABLE_2G *mp2; 995 char *value; 996 int rssi, cnt; 997 int from_app = 0; 998 999 from_app = check_user_agent(user_agent); 1000 1001 memset(mac, 0, sizeof(mac)); 1002 1003 /* query wl for authenticated sta list */ 1004 memset(data, 0, sizeof(data)); 1005 wrq.u.data.pointer = data; 1006 wrq.u.data.length = sizeof(data); 1007 wrq.u.data.flags = 0; 1008 if (wl_ioctl(WIF_2G, RTPRIV_IOCTL_GET_MAC_TABLE, &wrq) < 0) 1009 goto exit; 1010 1011 /* build wireless sta list */ 1012 firstRow = 1; 1013 mp2 = (RT_802_11_MAC_TABLE_2G *)wrq.u.data.pointer; 1014 for (i = 0; i<mp2->Num; i++) 1015 { 1016 rssi = cnt = 0; 1017 if (mp2->Entry[i].AvgRssi0) { 1018 rssi += mp2->Entry[i].AvgRssi0; 1019 cnt++; 1020 } 1021 if (mp2->Entry[i].AvgRssi1) { 1022 rssi += mp2->Entry[i].AvgRssi1; 1023 cnt++; 1024 } 1025 if (mp2->Entry[i].AvgRssi2) { 1026 rssi += mp2->Entry[i].AvgRssi2; 1027 cnt++; 1028 } 1029 if (cnt == 0) 1030 continue; //skip this sta info 1031 1032 if (firstRow == 1) 1033 firstRow = 0; 1034 else 1035 websWrite(wp, ", "); 1036 1037 if (from_app == 0) 1038 websWrite(wp, "["); 1039 1040 sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", 1041 mp2->Entry[i].Addr[0], mp2->Entry[i].Addr[1], 1042 mp2->Entry[i].Addr[2], mp2->Entry[i].Addr[3], 1043 mp2->Entry[i].Addr[4], mp2->Entry[i].Addr[5]); 1044 websWrite(wp, "\"%s\"", mac); 1045 1046 if (from_app != 0) { 1047 websWrite(wp, ":{"); 1048 websWrite(wp, "\"isWL\":"); 1049 } 1050 1051 value = "Yes"; 1052 if (from_app == 0) 1053 websWrite(wp, ", \"%s\"", value); 1054 else 1055 websWrite(wp, "\"%s\"", value); 1056 1057 value = ""; 1058 if (from_app == 0) 1059 websWrite(wp, ", \"%s\"", value); 1060 1061 if (from_app != 0) 1062 websWrite(wp, ",\"rssi\":"); 1063 1064 rssi = rssi / cnt; 1065 if (from_app == 0) 1066 websWrite(wp, ", \"%d\"", rssi); 1067 else 1068 websWrite(wp, "\"%d\"", rssi); 1069 1070 1071 if (from_app == 0) 1072 websWrite(wp, "]"); 1073 else 1074 websWrite(wp, "}"); 1075 } 1076 1077 /* error/exit */ 1078exit: 1079 return 0; 1080} 1081 1082int ej_wl_sta_list_5g(int eid, webs_t wp, int argc, char_t **argv) 1083{ 1084#if defined(RTCONFIG_HAS_5G) 1085 struct iwreq wrq; 1086 int i, firstRow; 1087 char data[16384]; 1088 char mac[ETHER_ADDR_STR_LEN]; 1089 RT_802_11_MAC_TABLE_5G *mp; 1090 char *value; 1091 int rssi, cnt; 1092 int from_app = 0; 1093 1094 from_app = check_user_agent(user_agent); 1095 1096 memset(mac, 0, sizeof(mac)); 1097 1098 /* query wl for authenticated sta list */ 1099 memset(data, 0, sizeof(data)); 1100 wrq.u.data.pointer = data; 1101 wrq.u.data.length = sizeof(data); 1102 wrq.u.data.flags = 0; 1103 if (wl_ioctl(WIF_5G, RTPRIV_IOCTL_GET_MAC_TABLE, &wrq) < 0) 1104 goto exit; 1105 1106 /* build wireless sta list */ 1107 firstRow = 1; 1108 mp = (RT_802_11_MAC_TABLE_5G *)wrq.u.data.pointer; 1109 for (i = 0; i<mp->Num; i++) 1110 { 1111 rssi = cnt = 0; 1112 if (mp->Entry[i].AvgRssi0) { 1113 rssi += mp->Entry[i].AvgRssi0; 1114 cnt++; 1115 } 1116 if (mp->Entry[i].AvgRssi1) { 1117 rssi += mp->Entry[i].AvgRssi1; 1118 cnt++; 1119 } 1120 if (mp->Entry[i].AvgRssi2) { 1121 rssi += mp->Entry[i].AvgRssi2; 1122 cnt++; 1123 } 1124 if (cnt == 0) 1125 continue; //skip this sta info 1126 1127 if (firstRow == 1) 1128 firstRow = 0; 1129 else 1130 websWrite(wp, ", "); 1131 1132 if (from_app == 0) 1133 websWrite(wp, "["); 1134 1135 sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", 1136 mp->Entry[i].Addr[0], mp->Entry[i].Addr[1], 1137 mp->Entry[i].Addr[2], mp->Entry[i].Addr[3], 1138 mp->Entry[i].Addr[4], mp->Entry[i].Addr[5]); 1139 websWrite(wp, "\"%s\"", mac); 1140 1141 if (from_app != 0) { 1142 websWrite(wp, ":{"); 1143 websWrite(wp, "\"isWL\":"); 1144 } 1145 1146 value = "Yes"; 1147 if (from_app == 0) 1148 websWrite(wp, ", \"%s\"", value); 1149 else 1150 websWrite(wp, "\"%s\"", value); 1151 1152 value = ""; 1153 if (from_app == 0) 1154 websWrite(wp, ", \"%s\"", value); 1155 1156 if (from_app != 0) 1157 websWrite(wp, ",\"rssi\":"); 1158 1159 rssi = rssi / cnt; 1160 if (from_app == 0) 1161 websWrite(wp, ", \"%d\"", rssi); 1162 else 1163 websWrite(wp, "\"%d\"", rssi); 1164 1165 1166 if (from_app == 0) 1167 websWrite(wp, "]"); 1168 else 1169 websWrite(wp, "}"); 1170 } 1171 1172 /* error/exit */ 1173#endif /* RTCONFIG_HAS_5G */ 1174exit: 1175 return 0; 1176} 1177 1178int ej_wl_auth_list(int eid, webs_t wp, int argc, char_t **argv) 1179{ 1180 struct iwreq wrq; 1181 int i, firstRow; 1182 char data[16384]; 1183 char mac[ETHER_ADDR_STR_LEN]; 1184 RT_802_11_MAC_TABLE_5G *mp; 1185 RT_802_11_MAC_TABLE_2G *mp2; 1186 char *value; 1187 1188 memset(mac, 0, sizeof(mac)); 1189 1190 /* query wl for authenticated sta list */ 1191 memset(data, 0, sizeof(data)); 1192 wrq.u.data.pointer = data; 1193 wrq.u.data.length = sizeof(data); 1194 wrq.u.data.flags = 0; 1195 if (wl_ioctl(WIF_2G, RTPRIV_IOCTL_GET_MAC_TABLE, &wrq) < 0) 1196 goto exit; 1197 1198 /* build wireless sta list */ 1199 firstRow = 1; 1200 mp2 = (RT_802_11_MAC_TABLE_2G *)wrq.u.data.pointer; 1201 for (i = 0; i<mp2->Num; i++) 1202 { 1203 if (firstRow == 1) 1204 firstRow = 0; 1205 else 1206 websWrite(wp, ", "); 1207 websWrite(wp, "["); 1208 1209 sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", 1210 mp2->Entry[i].Addr[0], mp2->Entry[i].Addr[1], 1211 mp2->Entry[i].Addr[2], mp2->Entry[i].Addr[3], 1212 mp2->Entry[i].Addr[4], mp2->Entry[i].Addr[5]); 1213 websWrite(wp, "\"%s\"", mac); 1214 1215 value = "Yes"; 1216 websWrite(wp, ", \"%s\"", value); 1217 1218 value = ""; 1219 websWrite(wp, ", \"%s\"", value); 1220 1221 websWrite(wp, "]"); 1222 } 1223 1224#if defined(RTCONFIG_HAS_5G) 1225 /* query wl for authenticated sta list */ 1226 memset(data, 0, sizeof(data)); 1227 wrq.u.data.pointer = data; 1228 wrq.u.data.length = sizeof(data); 1229 wrq.u.data.flags = 0; 1230 if (wl_ioctl(WIF_5G, RTPRIV_IOCTL_GET_MAC_TABLE, &wrq) < 0) 1231 goto exit; 1232 1233 /* build wireless sta list */ 1234 mp = (RT_802_11_MAC_TABLE_5G *)wrq.u.data.pointer; 1235 for (i = 0; i<mp->Num; i++) 1236 { 1237 if (firstRow == 1) 1238 firstRow = 0; 1239 else 1240 websWrite(wp, ", "); 1241 websWrite(wp, "["); 1242 1243 sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", 1244 mp->Entry[i].Addr[0], mp->Entry[i].Addr[1], 1245 mp->Entry[i].Addr[2], mp->Entry[i].Addr[3], 1246 mp->Entry[i].Addr[4], mp->Entry[i].Addr[5]); 1247 websWrite(wp, "\"%s\"", mac); 1248 1249 value = "Yes"; 1250 websWrite(wp, ", \"%s\"", value); 1251 1252 value = ""; 1253 websWrite(wp, ", \"%s\"", value); 1254 1255 websWrite(wp, "]"); 1256 } 1257#endif /* RTCONFIG_HAS_5G */ 1258 1259 /* error/exit */ 1260exit: 1261 return 0; 1262} 1263#if defined(RTN65U) 1264static void convertToUpper(char *str) 1265{ 1266 if(str == NULL) 1267 return; 1268 while(*str) 1269 { 1270 if(*str >= 'a' && *str <= 'z') 1271 { 1272 *str &= (unsigned char)~0x20; 1273 } 1274 str++; 1275 } 1276} 1277#endif 1278static int wl_scan(int eid, webs_t wp, int argc, char_t **argv, int unit) 1279{ 1280 int retval = 0, i = 0, apCount = 0; 1281 char data[8192]; 1282 char ssid_str[256]; 1283 char header[128]; 1284 struct iwreq wrq; 1285 SSA *ssap; 1286 char tmp[128], prefix[] = "wlXXXXXXXXXX_"; 1287 int lock; 1288 1289 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 1290 memset(data, 0x00, 255); 1291 strcpy(data, "SiteSurvey=1"); 1292 wrq.u.data.length = strlen(data)+1; 1293 wrq.u.data.pointer = data; 1294 wrq.u.data.flags = 0; 1295 1296 lock = file_lock("nvramcommit"); 1297 if (wl_ioctl(nvram_safe_get(strcat_r(prefix, "ifname", tmp)), RTPRIV_IOCTL_SET, &wrq) < 0) 1298 { 1299 file_unlock(lock); 1300 dbg("Site Survey fails\n"); 1301 return 0; 1302 } 1303 file_unlock(lock); 1304 dbg("Please wait"); 1305 sleep(1); 1306 dbg("."); 1307 sleep(1); 1308 dbg("."); 1309 sleep(1); 1310 dbg("."); 1311 sleep(1); 1312 dbg(".\n\n"); 1313 memset(data, 0, 8192); 1314 strcpy(data, ""); 1315 wrq.u.data.length = 8192; 1316 wrq.u.data.pointer = data; 1317 wrq.u.data.flags = 0; 1318 if (wl_ioctl(nvram_safe_get(strcat_r(prefix, "ifname", tmp)), RTPRIV_IOCTL_GSITESURVEY, &wrq) < 0) 1319 { 1320 dbg("errors in getting site survey result\n"); 1321 return 0; 1322 } 1323 memset(header, 0, sizeof(header)); 1324 //sprintf(header, "%-3s%-33s%-18s%-8s%-15s%-9s%-8s%-2s\n", "Ch", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode", "NT"); 1325#if 0// defined(RTN14U) 1326 sprintf(header, "%-4s%-33s%-18s%-9s%-16s%-9s%-8s%-4s%-5s\n", "Ch", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode"," WPS", " DPID"); 1327#else 1328 sprintf(header, "%-4s%-33s%-18s%-9s%-16s%-9s%-8s\n", "Ch", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode"); 1329#endif 1330 dbg("\n%s", header); 1331 if (wrq.u.data.length > 0) 1332 { 1333#if defined(RTN65U) 1334 if (unit == 0 && get_model() == MODEL_RTN65U) 1335 { 1336 char *encryption; 1337 SITE_SURVEY_RT3352_iNIC *pSsap, *ssAP; 1338 1339 pSsap = ssAP = (SITE_SURVEY_RT3352_iNIC *) (1 /* '\n' */ + wrq.u.data.pointer + sizeof(SITE_SURVEY_RT3352_iNIC) /* header */); 1340 while(((unsigned int)wrq.u.data.pointer + wrq.u.data.length) > (unsigned int) ssAP) 1341 { 1342 ssAP->channel [sizeof(ssAP->channel) -1] = '\0'; 1343 ssAP->ssid [32 ] = '\0'; 1344 ssAP->bssid [17 ] = '\0'; 1345 ssAP->encryption[sizeof(ssAP->encryption) -1] = '\0'; 1346 if((encryption = strchr(ssAP->authmode, '/')) != NULL) 1347 { 1348 memmove(ssAP->encryption, encryption +1, sizeof(ssAP->encryption) -1); 1349 memset(encryption, ' ', sizeof(ssAP->authmode) - (encryption - ssAP->authmode)); 1350 *encryption = '\0'; 1351 } 1352 ssAP->authmode [sizeof(ssAP->authmode) -1] = '\0'; 1353 ssAP->signal [sizeof(ssAP->signal) -1] = '\0'; 1354 ssAP->wmode [sizeof(ssAP->wmode) -1] = '\0'; 1355 ssAP->extch [sizeof(ssAP->extch) -1] = '\0'; 1356 ssAP->nt [sizeof(ssAP->nt) -1] = '\0'; 1357 ssAP->wps [sizeof(ssAP->wps) -1] = '\0'; 1358 ssAP->dpid [sizeof(ssAP->dpid) -1] = '\0'; 1359 1360 convertToUpper(ssAP->bssid); 1361 ssAP++; 1362 apCount++; 1363 } 1364 1365 if (apCount) 1366 { 1367 retval += websWrite(wp, "["); 1368 for (i = 0; i < apCount; i++) 1369 { 1370 dbg("%-4s%-33s%-18s%-9s%-16s%-9s%-8s\n", 1371 pSsap[i].channel, 1372 pSsap[i].ssid, 1373 pSsap[i].bssid, 1374 pSsap[i].encryption, 1375 pSsap[i].authmode, 1376 pSsap[i].signal, 1377 pSsap[i].wmode 1378 ); 1379 1380 memset(ssid_str, 0, sizeof(ssid_str)); 1381 char_to_ascii(ssid_str, trim_r(pSsap[i].ssid)); 1382 1383 if (!i) 1384 retval += websWrite(wp, "[\"%s\", \"%s\"]", ssid_str, pSsap[i].bssid); 1385 else 1386 retval += websWrite(wp, ", [\"%s\", \"%s\"]", ssid_str, pSsap[i].bssid); 1387 } 1388 retval += websWrite(wp, "]"); 1389 dbg("\n"); 1390 } 1391 else 1392 retval += websWrite(wp, "[]"); 1393 return retval; 1394 } 1395#endif 1396 ssap=(SSA *)(wrq.u.data.pointer+strlen(header)+1); 1397 int len = strlen(wrq.u.data.pointer+strlen(header))-1; 1398 char *sp, *op; 1399 op = sp = wrq.u.data.pointer+strlen(header)+1; 1400 while (*sp && ((len - (sp-op)) >= 0)) 1401 { 1402 ssap->SiteSurvey[i].channel[3] = '\0'; 1403 ssap->SiteSurvey[i].ssid[32] = '\0'; 1404 ssap->SiteSurvey[i].bssid[17] = '\0'; 1405 ssap->SiteSurvey[i].encryption[8] = '\0'; 1406 ssap->SiteSurvey[i].authmode[15] = '\0'; 1407 ssap->SiteSurvey[i].signal[8] = '\0'; 1408 ssap->SiteSurvey[i].wmode[7] = '\0'; 1409#if 0//defined(RTN14U) 1410 ssap->SiteSurvey[i].wps[3] = '\0'; 1411 ssap->SiteSurvey[i].dpid[4] = '\0'; 1412#endif 1413 sp+=strlen(header); 1414 apCount=++i; 1415 } 1416 if (apCount) 1417 { 1418 retval += websWrite(wp, "["); 1419 for (i = 0; i < apCount; i++) 1420 { 1421 dbg("\napCount=%d\n",i); 1422 dbg( 1423#if 0//defined(RTN14U) 1424 "%-4s%-33s%-18s%-9s%-16s%-9s%-8s%-4s%-5s\n", 1425#else 1426 "%-4s%-33s%-18s%-9s%-16s%-9s%-8s\n", 1427#endif 1428 ssap->SiteSurvey[i].channel, 1429 (char*)ssap->SiteSurvey[i].ssid, 1430 ssap->SiteSurvey[i].bssid, 1431 ssap->SiteSurvey[i].encryption, 1432 ssap->SiteSurvey[i].authmode, 1433 ssap->SiteSurvey[i].signal, 1434 ssap->SiteSurvey[i].wmode 1435#if 0//defined(RTN14U) 1436 , ssap->SiteSurvey[i].wps 1437 , ssap->SiteSurvey[i].dpid 1438#endif 1439 ); 1440 1441 memset(ssid_str, 0, sizeof(ssid_str)); 1442 char_to_ascii(ssid_str, trim_r(ssap->SiteSurvey[i].ssid)); 1443 1444 if (!i) 1445// retval += websWrite(wp, "\"%s\"", ssap->SiteSurvey[i].bssid); 1446 retval += websWrite(wp, "[\"%s\", \"%s\"]", ssid_str, ssap->SiteSurvey[i].bssid); 1447 else 1448// retval += websWrite(wp, ", \"%s\"", ssap->SiteSurvey[i].bssid); 1449 retval += websWrite(wp, ", [\"%s\", \"%s\"]", ssid_str, ssap->SiteSurvey[i].bssid); 1450 } 1451 retval += websWrite(wp, "]"); 1452 dbg("\n"); 1453 } 1454 else 1455 retval += websWrite(wp, "[]"); 1456 } 1457 return retval; 1458} 1459 1460int 1461ej_wl_scan(int eid, webs_t wp, int argc, char_t **argv) 1462{ 1463 return wl_scan(eid, wp, argc, argv, 0); 1464} 1465 1466int 1467ej_wl_scan_2g(int eid, webs_t wp, int argc, char_t **argv) 1468{ 1469 return wl_scan(eid, wp, argc, argv, 0); 1470} 1471 1472int 1473ej_wl_scan_5g(int eid, webs_t wp, int argc, char_t **argv) 1474{ 1475 return wl_scan(eid, wp, argc, argv, 1); 1476} 1477 1478 1479static int ej_wl_channel_list(int eid, webs_t wp, int argc, char_t **argv, int unit) 1480{ 1481 int retval = 0; 1482 char tmp[128], prefix[] = "wlXXXXXXXXXX_"; 1483 char *country_code; 1484 char chList[256]; 1485 int band; 1486 1487 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 1488 country_code = nvram_get(strcat_r(prefix, "country_code", tmp)); 1489 band = unit; 1490 1491 if (country_code == NULL || strlen(country_code) != 2) return retval; 1492 1493 if (band != 0 && band != 1) return retval; 1494 1495 //try getting channel list via wifi driver first 1496 if(get_channel_list_via_driver(unit, chList, sizeof(chList)) > 0) 1497 { 1498 retval += websWrite(wp, "[%s]", chList); 1499 } 1500 else if(get_channel_list_via_country(unit, country_code, chList, sizeof(chList)) > 0) 1501 { 1502 retval += websWrite(wp, "[%s]", chList); 1503 } 1504 return retval; 1505} 1506 1507 1508int 1509ej_wl_channel_list_2g(int eid, webs_t wp, int argc, char_t **argv) 1510{ 1511 return ej_wl_channel_list(eid, wp, argc, argv, 0); 1512} 1513 1514int 1515ej_wl_channel_list_5g(int eid, webs_t wp, int argc, char_t **argv) 1516{ 1517 return ej_wl_channel_list(eid, wp, argc, argv, 1); 1518} 1519 1520 1521static int ej_wl_rate(int eid, webs_t wp, int argc, char_t **argv, int unit) 1522{ 1523 struct iwreq wrq; 1524 int retval = 0; 1525 char tmp[256], prefix[] = "wlXXXXXXXXXX_"; 1526 char *name; 1527 char word[256], *next; 1528 int unit_max = 0; 1529 int rate=0; 1530 int status; 1531 char rate_buf[32]; 1532 int sw_mode = nvram_get_int("sw_mode"); 1533 int wlc_band = nvram_get_int("wlc_band"); 1534 1535 sprintf(rate_buf, "0 Mbps"); 1536 1537 foreach (word, nvram_safe_get("wl_ifnames"), next) 1538 unit_max++; 1539 1540 if (unit > (unit_max - 1)) 1541 goto ERROR; 1542 1543 if (wlc_band == unit && (sw_mode == SW_MODE_REPEATER || sw_mode == SW_MODE_HOTSPOT)) 1544 snprintf(prefix, sizeof(prefix), "wl%d.1_", unit); 1545 else 1546#if 0 1547 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 1548 1549 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1550 1551 wrq.u.bitrate.value=-1; 1552 if (wl_ioctl(name, SIOCGIWRATE, &wrq)) 1553 { 1554 dbG("can not get rate info of %s\n", name); 1555 goto ERROR; 1556 } 1557 1558 rate = wrq.u.bitrate.value; 1559 if ((rate == -1) || (rate == 0)) 1560 sprintf(rate_buf, "auto"); 1561 else 1562 sprintf(rate_buf, "%d Mbps", (rate / 1000000)); 1563#else 1564 goto ERROR; 1565 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 1566 1567 memset(tmp, 0x00, sizeof(tmp)); 1568 wrq.u.data.length = sizeof(tmp); 1569 wrq.u.data.pointer = (caddr_t) tmp; 1570 wrq.u.data.flags = ASUS_SUBCMD_CONN_STATUS; 1571 1572 if (wl_ioctl(name, RTPRIV_IOCTL_ASUSCMD, &wrq) < 0) 1573 { 1574 dbg("%s: errors in getting %s CONN_STATUS result\n", __func__, name); 1575 goto ERROR; 1576 } 1577 status = ((int*)tmp)[0]; 1578 rate = ((int*)tmp)[1]; 1579 1580 if(status == 6) 1581 sprintf(rate_buf, "%d Mbps", rate); 1582#endif 1583 1584ERROR: 1585 retval += websWrite(wp, "%s", rate_buf); 1586 return retval; 1587} 1588 1589 1590int 1591ej_wl_rate_2g(int eid, webs_t wp, int argc, char_t **argv) 1592{ 1593 if(nvram_match("sw_mode", "2")) 1594 return ej_wl_rate(eid, wp, argc, argv, 0); 1595 else 1596 return 0; 1597} 1598 1599int 1600ej_wl_rate_5g(int eid, webs_t wp, int argc, char_t **argv) 1601{ 1602 if(nvram_match("sw_mode", "2")) 1603 return ej_wl_rate(eid, wp, argc, argv, 1); 1604 else 1605 return 0; 1606} 1607 1608#ifdef RTCONFIG_PROXYSTA 1609int 1610ej_wl_auth_psta(int eid, webs_t wp, int argc, char_t **argv) 1611{ 1612 int retval = 0; 1613 1614 if(nvram_match("wlc_state", "2")) //connected 1615 retval += websWrite(wp, "wlc_state=1;wlc_state_auth=0;"); 1616 //else if(?) //authorization failed 1617 // retval += websWrite(wp, "wlc_state=2;wlc_state_auth=1;"); 1618 else //disconnected 1619 retval += websWrite(wp, "wlc_state=0;wlc_state_auth=0;"); 1620 1621 return retval; 1622} 1623#endif 1624