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 * Copyright 2012, ASUSTeK Inc. 18 * All Rights Reserved. 19 * 20 * THIS SOFTWARE IS OFFERED "AS IS", AND ASUS GRANTS NO WARRANTIES OF ANY 21 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 22 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 23 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 24 * 25 */ 26 27#include <stdio.h> 28#include <stdlib.h> 29#include <string.h> 30#include <sys/time.h> 31#include <unistd.h> 32#include <bcmnvram.h> 33#include <bcmutils.h> 34#include <wlutils.h> 35#include <shutils.h> 36#include <shared.h> 37#include <wlioctl.h> 38#ifdef PSTA_DEBUG 39#include <rc.h> 40#else 41#include <signal.h> 42#endif 43 44#include <wlscan.h> 45#ifdef RTCONFIG_BCM_7114 46#include <bcmutils.h> 47#include <bcmendian.h> 48#include <security_ipc.h> 49#endif 50 51#ifdef RTCONFIG_BCMWL6 52#ifdef RTCONFIG_PROXYSTA 53 54#define NORMAL_PERIOD 30 55#define MAX_STA_COUNT 128 56#define NVRAM_BUFSIZE 100 57 58int psta_debug = 0; 59int count_bss_down = 0; 60#ifdef PSTA_DEBUG 61static int count = -1; 62#endif 63 64/* WPS ENR mode APIs */ 65typedef struct wlc_ap_list_info 66{ 67#if 0 68 bool used; 69#endif 70 uint8 ssid[33]; 71 uint8 ssidLen; 72 uint8 BSSID[6]; 73#if 0 74 uint8 *ie_buf; 75 uint32 ie_buflen; 76#endif 77 uint8 channel; 78#if 0 79 uint8 wep; 80#endif 81} wlc_ap_list_info_t; 82 83#define WLC_SCAN_RETRY_TIMES 5 84#define NUMCHANS 64 85#define MAX_SSID_LEN 32 86 87static wlc_ap_list_info_t ap_list[MAX_NUMBER_OF_APINFO]; 88static char scan_result[WLC_SCAN_RESULT_BUF_LEN]; 89 90/* The below macro handle endian mis-matches between wl utility and wl driver. */ 91static bool g_swap = FALSE; 92#define htod32(i) (g_swap?bcmswap32(i):(uint32)(i)) 93#define dtoh32(i) (g_swap?bcmswap32(i):(uint32)(i)) 94 95#ifdef RTCONFIG_BCM_7114 96typedef struct escan_wksp_s { 97 uint8 packet[4096]; 98 int event_fd; 99} escan_wksp_t; 100 101static escan_wksp_t *d_info; 102 103/* open a UDP packet to event dispatcher for receiving/sending data */ 104static int 105escan_open_eventfd() 106{ 107 int reuse = 1; 108 struct sockaddr_in sockaddr; 109 int fd = -1; 110 111 d_info->event_fd = -1; 112 113 /* open loopback socket to communicate with event dispatcher */ 114 memset(&sockaddr, 0, sizeof(sockaddr)); 115 sockaddr.sin_family = AF_INET; 116 sockaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 117 sockaddr.sin_port = htons(EAPD_WKSP_DCS_UDP_SPORT); 118 119 if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 120 dbg("Unable to create loopback socket\n"); 121 goto exit; 122 } 123 124 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0) { 125 dbg("Unable to setsockopt to loopback socket %d.\n", fd); 126 goto exit; 127 } 128 129 if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { 130 dbg("Unable to bind to loopback socket %d\n", fd); 131 goto exit; 132 } 133 134 d_info->event_fd = fd; 135 136 return 0; 137 138 /* error handling */ 139exit: 140 if (fd != -1) { 141 close(fd); 142 } 143 144 return errno; 145} 146 147static bool escan_swap = FALSE; 148#define htod16(i) (escan_swap?bcmswap16(i):(uint16)(i)) 149#define WL_EVENT_TIMEOUT 10 150 151struct escan_bss { 152 struct escan_bss *next; 153 wl_bss_info_t bss[1]; 154}; 155#define ESCAN_BSS_FIXED_SIZE 4 156 157/* listen to sockets and receive escan results */ 158static int 159get_scan_escan(char *scan_buf, uint buf_len) 160{ 161 fd_set fdset; 162 int fd; 163 struct timeval tv; 164 uint8 *pkt; 165 int len; 166 int retval; 167 wl_escan_result_t *escan_data; 168 struct escan_bss *escan_bss_head = NULL; 169 struct escan_bss *escan_bss_tail = NULL; 170 struct escan_bss *result; 171 172 d_info = (escan_wksp_t*)malloc(sizeof(escan_wksp_t)); 173 174 escan_open_eventfd(); 175 176 if (d_info->event_fd == -1) { 177 return -1; 178 } 179 180 fd = d_info->event_fd; 181 182 FD_ZERO(&fdset); 183 FD_SET(fd, &fdset); 184 185 pkt = d_info->packet; 186 len = sizeof(d_info->packet); 187 188 tv.tv_sec = WL_EVENT_TIMEOUT; 189 tv.tv_usec = 0; 190 191 /* listen to data availible on all sockets */ 192 while ((retval = select(fd+1, &fdset, NULL, NULL, &tv)) > 0) { 193 bcm_event_t *pvt_data; 194 uint32 evt_type; 195 uint32 status; 196 197 if (recv(fd, pkt, len, 0) <= 0) 198 continue; 199 200 pvt_data = (bcm_event_t *)(pkt + IFNAMSIZ); 201 evt_type = ntoh32(pvt_data->event.event_type); 202 203 if (evt_type == WLC_E_ESCAN_RESULT) { 204 escan_data = (wl_escan_result_t*)(pvt_data + 1); 205 status = ntoh32(pvt_data->event.status); 206 207 if (status == WLC_E_STATUS_PARTIAL) { 208 wl_bss_info_t *bi = &escan_data->bss_info[0]; 209 wl_bss_info_t *bss = NULL; 210 211 /* check if we've received info of same BSSID */ 212 for (result = escan_bss_head; result; result = result->next) { 213 bss = result->bss; 214 215 if (!memcmp(bi->BSSID.octet, bss->BSSID.octet, 216 ETHER_ADDR_LEN) && 217 CHSPEC_BAND(bi->chanspec) == 218 CHSPEC_BAND(bss->chanspec) && 219 bi->SSID_len == bss->SSID_len && 220 !memcmp(bi->SSID, bss->SSID, bi->SSID_len)) 221 break; 222 } 223 224 if (!result) { 225 /* New BSS. Allocate memory and save it */ 226 struct escan_bss *ebss = (struct escan_bss *)malloc( 227 OFFSETOF(struct escan_bss, bss) + bi->length); 228 229 if (!ebss) { 230 dbg("can't allocate memory for bss"); 231 goto exit; 232 } 233 234 ebss->next = NULL; 235 memcpy(&ebss->bss, bi, bi->length); 236 if (escan_bss_tail) { 237 escan_bss_tail->next = ebss; 238 } 239 else { 240 escan_bss_head = ebss; 241 } 242 escan_bss_tail = ebss; 243 } 244 else if (bi->RSSI != WLC_RSSI_INVALID) { 245 /* We've got this BSS. Update rssi if necessary */ 246 if (((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 247 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) && 248 ((bss->RSSI == WLC_RSSI_INVALID) || 249 (bss->RSSI < bi->RSSI))) { 250 /* preserve max RSSI if the measurements are 251 * both on-channel or both off-channel 252 */ 253 bss->RSSI = bi->RSSI; 254 bss->SNR = bi->SNR; 255 bss->phy_noise = bi->phy_noise; 256 } else if ((bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) && 257 (bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) { 258 /* preserve the on-channel rssi measurement 259 * if the new measurement is off channel 260 */ 261 bss->RSSI = bi->RSSI; 262 bss->SNR = bi->SNR; 263 bss->phy_noise = bi->phy_noise; 264 bss->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL; 265 } 266 } 267 } 268 else if (status == WLC_E_STATUS_SUCCESS) { 269 /* Escan finished. Let's go dump the results. */ 270 break; 271 } 272 else { 273 dbg("sync_id: %d, status:%d, misc. error/abort\n", 274 escan_data->sync_id, status); 275 goto exit; 276 } 277 } 278 } 279 280 if (retval > 0) { 281 wl_scan_results_t* s_result = (wl_scan_results_t*)scan_buf; 282 wl_bss_info_t *bi = s_result->bss_info; 283 wl_bss_info_t *bss; 284 285 s_result->count = 0; 286 len = buf_len - WL_SCAN_RESULTS_FIXED_SIZE; 287 288 for (result = escan_bss_head; result; result = result->next) { 289 bss = result->bss; 290 if (buf_len < bss->length) { 291 dbg("Memory not enough for scan results\n"); 292 break; 293 } 294 memcpy(bi, bss, bss->length); 295 bi = (wl_bss_info_t*)((int8*)bi + bss->length); 296 len -= bss->length; 297 s_result->count++; 298 } 299 } else if (retval == 0) { 300 dbg("Scan timeout!\n"); 301 } else { 302 dbg("Receive scan results failed!\n"); 303 } 304 305exit: 306 if (d_info) { 307 if (d_info->event_fd != -1) { 308 close(d_info->event_fd); 309 d_info->event_fd = -1; 310 } 311 312 free(d_info); 313 } 314 315 /* free scan results */ 316 result = escan_bss_head; 317 while (result) { 318 struct escan_bss *tmp = result->next; 319 free(result); 320 result = tmp; 321 } 322 323 return (retval > 0) ? BCME_OK : BCME_ERROR; 324} 325 326static char * 327wl_get_scan_results_escan(int unit) 328{ 329 int ret, retry_times = 0; 330 wl_escan_params_t *params = NULL; 331 int params_size = WL_SCAN_PARAMS_FIXED_SIZE + NUMCHANS * sizeof(uint16); 332 wlc_ssid_t wst = {0, ""}; 333 int org_scan_time = 20, scan_time = 40; 334 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 335 char *ifname = NULL; 336 337 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 338 wst.SSID_len = strlen(nvram_safe_get(strcat_r(prefix, "ssid", tmp))); 339 if (wst.SSID_len <= MAX_SSID_LEN) 340 memcpy(wst.SSID, nvram_safe_get(strcat_r(prefix, "ssid", tmp)), wst.SSID_len); 341 else 342 wst.SSID_len = 0; 343 344 params = (wl_escan_params_t*)malloc(params_size); 345 if (params == NULL) { 346 return NULL; 347 } 348 349 memset(params, 0, params_size); 350 params->params.ssid = wst; 351 params->params.bss_type = DOT11_BSSTYPE_ANY; 352 memcpy(¶ms->params.bssid, ðer_bcast, ETHER_ADDR_LEN); 353 params->params.scan_type = -1; 354 params->params.nprobes = -1; 355 params->params.active_time = -1; 356 params->params.passive_time = -1; 357 params->params.home_time = -1; 358 params->params.channel_num = 0; 359 360 params->version = htod32(ESCAN_REQ_VERSION); 361 params->action = htod16(WL_SCAN_ACTION_START); 362 363 srand((unsigned int)uptime()); 364 params->sync_id = htod16(rand() & 0xffff); 365 366 params_size += OFFSETOF(wl_escan_params_t, params); 367 368 ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 369 /* extend scan channel time to get more AP probe resp */ 370 wl_ioctl(ifname, WLC_GET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time)); 371 if (org_scan_time < scan_time) 372 wl_ioctl(ifname, WLC_SET_SCAN_CHANNEL_TIME, &scan_time, sizeof(scan_time)); 373 374retry: 375 ret = wl_iovar_set(ifname, "escan", params, params_size); 376 if (ret < 0) { 377 if (retry_times++ < WLC_SCAN_RETRY_TIMES) { 378 if (psta_debug) 379 dbg("set escan command failed, retry %d\n", retry_times); 380 sleep(1); 381 goto retry; 382 } 383 } 384 385 sleep(2); 386 387 ret = get_scan_escan(scan_result, WLC_SCAN_RESULT_BUF_LEN); 388 if (ret < 0 && retry_times++ < WLC_SCAN_RETRY_TIMES) { 389 if (psta_debug) 390 dbg("get scan result failed, retry %d\n", retry_times); 391 sleep(1); 392 goto retry; 393 } 394 395 free(params); 396 397 /* restore original scan channel time */ 398 wl_ioctl(ifname, WLC_SET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time)); 399 400 if (ret < 0) 401 return NULL; 402 403 return scan_result; 404} 405 406#else 407 408static char * 409wl_get_scan_results(int unit) 410{ 411 int ret, retry_times = 0; 412 wl_scan_params_t *params; 413 wl_scan_results_t *list = (wl_scan_results_t*)scan_result; 414 int params_size = WL_SCAN_PARAMS_FIXED_SIZE + NUMCHANS * sizeof(uint16); 415 wlc_ssid_t wst = {0, ""}; 416 int org_scan_time = 20, scan_time = 40; 417 char tmp[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 418 char *ifname = NULL; 419 420 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 421 wst.SSID_len = strlen(nvram_safe_get(strcat_r(prefix, "ssid", tmp))); 422 if (wst.SSID_len <= MAX_SSID_LEN) 423 memcpy(wst.SSID, nvram_safe_get(strcat_r(prefix, "ssid", tmp)), wst.SSID_len); 424 else 425 wst.SSID_len = 0; 426 427 params = (wl_scan_params_t*)malloc(params_size); 428 if (params == NULL) { 429 return NULL; 430 } 431 432 memset(params, 0, params_size); 433 params->ssid = wst; 434 params->bss_type = DOT11_BSSTYPE_ANY; 435 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); 436 params->scan_type = -1; 437 params->nprobes = -1; 438 params->active_time = -1; 439 params->passive_time = -1; 440 params->home_time = -1; 441 params->channel_num = 0; 442 443 ifname = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 444 /* extend scan channel time to get more AP probe resp */ 445 wl_ioctl(ifname, WLC_GET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time)); 446 if (org_scan_time < scan_time) 447 wl_ioctl(ifname, WLC_SET_SCAN_CHANNEL_TIME, &scan_time, sizeof(scan_time)); 448 449retry: 450 ret = wl_ioctl(ifname, WLC_SCAN, params, params_size); 451 if (ret < 0) { 452 if (retry_times++ < WLC_SCAN_RETRY_TIMES) { 453 if (psta_debug) 454 dbg("set scan command failed, retry %d\n", retry_times); 455 sleep(1); 456 goto retry; 457 } 458 } 459 460 sleep(2); 461 462 list->buflen = WLC_SCAN_RESULT_BUF_LEN; 463 ret = wl_ioctl(ifname, WLC_SCAN_RESULTS, scan_result, WLC_SCAN_RESULT_BUF_LEN); 464 if (ret < 0 && retry_times++ < WLC_SCAN_RETRY_TIMES) { 465 if (psta_debug) 466 dbg("get scan result failed, retry %d\n", retry_times); 467 sleep(1); 468 goto retry; 469 } 470 471 free(params); 472 473 /* restore original scan channel time */ 474 wl_ioctl(ifname, WLC_SET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time)); 475 476 if (ret < 0) 477 return NULL; 478 479 return scan_result; 480} 481#endif 482 483static int 484wl_scan(int unit) 485{ 486 wl_scan_results_t *list = (wl_scan_results_t*)scan_result; 487 wl_bss_info_t *bi; 488 wl_bss_info_107_t *old_bi; 489 uint i, ap_count = 0; 490 char ssid_str[128], macstr[18]; 491 492#ifdef RTCONFIG_BCM_7114 493 if (wl_get_scan_results_escan(unit) == NULL) 494#else 495 if (wl_get_scan_results(unit) == NULL) 496#endif 497 return 0; 498 499 if (list->count == 0) 500 return 0; 501#ifndef RTCONFIG_BCM_7114 502 else if (list->version != WL_BSS_INFO_VERSION && 503 list->version != LEGACY_WL_BSS_INFO_VERSION && 504 list->version != LEGACY2_WL_BSS_INFO_VERSION) { 505 dbg("Sorry, your driver has bss_info_version %d " 506 "but this program supports only version %d.\n", 507 list->version, WL_BSS_INFO_VERSION); 508 return 0; 509 } 510#endif 511 512 memset(ap_list, 0, sizeof(ap_list)); 513 bi = list->bss_info; 514 for (i = 0; i < list->count; i++) { 515 /* Convert version 107 to 109 */ 516 if (dtoh32(bi->version) == LEGACY_WL_BSS_INFO_VERSION) { 517 old_bi = (wl_bss_info_107_t *)bi; 518 bi->chanspec = CH20MHZ_CHSPEC(old_bi->channel); 519 bi->ie_length = old_bi->ie_length; 520 bi->ie_offset = sizeof(wl_bss_info_107_t); 521 } 522 523 if (bi->ie_length) { 524 if (ap_count < MAX_NUMBER_OF_APINFO) { 525#if 0 526 ap_list[ap_count].used = TRUE; 527#endif 528 memcpy(ap_list[ap_count].BSSID, (uint8 *)&bi->BSSID, 6); 529 strncpy((char *)ap_list[ap_count].ssid, (char *)bi->SSID, bi->SSID_len); 530 ap_list[ap_count].ssid[bi->SSID_len] = '\0'; 531 ap_list[ap_count].ssidLen= bi->SSID_len; 532#if 0 533 ap_list[ap_count].ie_buf = (uint8 *)(((uint8 *)bi) + bi->ie_offset); 534 ap_list[ap_count].ie_buflen = bi->ie_length; 535#endif 536 if (dtoh32(bi->version) != LEGACY_WL_BSS_INFO_VERSION && bi->n_cap) 537 ap_list[ap_count].channel= bi->ctl_ch; 538 else 539 ap_list[ap_count].channel= (bi->chanspec & WL_CHANSPEC_CHAN_MASK); 540#if 0 541 ap_list[ap_count].wep = bi->capability & DOT11_CAP_PRIVACY; 542#endif 543 ap_count++; 544 } 545 } 546 bi = (wl_bss_info_t*)((int8*)bi + bi->length); 547 } 548 549 if (ap_count) 550 { 551 if (psta_debug) 552 dbg("%-4s%-33s%-18s\n", "Ch", "SSID", "BSSID"); 553 554 for (i = 0; i < ap_count; i++) 555 { 556 memset(ssid_str, 0, sizeof(ssid_str)); 557 char_to_ascii(ssid_str, (const char *) trim_r(ap_list[i].ssid)); 558 559 ether_etoa((const unsigned char *) &ap_list[i].BSSID, macstr); 560 if (psta_debug) 561 dbg("%-4d%-33s%-18s\n", 562 ap_list[i].channel, 563 ap_list[i].ssid, 564 macstr 565 ); 566 } 567 } 568 569 return ap_count; 570} 571 572static struct itimerval itv; 573static void 574alarmtimer(unsigned long sec, unsigned long usec) 575{ 576 itv.it_value.tv_sec = sec; 577 itv.it_value.tv_usec = usec; 578 itv.it_interval = itv.it_value; 579 setitimer(ITIMER_REAL, &itv, NULL); 580} 581 582static int 583wl_autho(char *name, struct ether_addr *ea) 584{ 585 char buf[sizeof(sta_info_t)]; 586 587 strcpy(buf, "sta_info"); 588 memcpy(buf + strlen(buf) + 1, (unsigned char *)ea, ETHER_ADDR_LEN); 589 590 if (!wl_ioctl(name, WLC_GET_VAR, buf, sizeof(buf))) { 591 sta_info_t *sta = (sta_info_t *)buf; 592 uint32 f = sta->flags; 593 594 if (f & WL_STA_AUTHO) 595 return 1; 596 } 597 598 return 0; 599} 600#ifdef PSTA_DEBUG 601static void check_wl_rate(const char *ifname) 602{ 603 int rate = 0; 604 char rate_buf[32]; 605 606 sprintf(rate_buf, "0 Mbps"); 607 608 if (wl_ioctl(ifname, WLC_GET_RATE, &rate, sizeof(int))) 609 { 610 dbG("can not get rate info of %s\n", ifname); 611 goto ERROR; 612 } 613 else 614 { 615 rate = dtoh32(rate); 616 if ((rate == -1) || (rate == 0)) 617 sprintf(rate_buf, "auto"); 618 else 619 sprintf(rate_buf, "%d%s Mbps", (rate / 2), (rate & 1) ? ".5" : ""); 620 } 621 622ERROR: 623 logmessage(LOGNAME, "wl interface %s data rate: %s", ifname, rate_buf); 624} 625#endif 626static void 627psta_keepalive(int ex) 628{ 629 char tmp[NVRAM_BUFSIZE], tmp2[NVRAM_BUFSIZE], prefix[] = "wlXXXXXXXXXX_"; 630 char *name = NULL; 631 struct maclist *mac_list = NULL; 632 int mac_list_size, i, unit; 633 int psta = 0; 634 struct ether_addr bssid; 635 unsigned char bssid_null[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; 636 char macaddr[18]; 637 char band_var[16]; 638 639 sprintf(band_var, "wlc_band%s", ex ? "_ex" : ""); 640 unit = nvram_get_int(band_var); 641 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 642 643 if (!nvram_match(strcat_r(prefix, "mode", tmp), "psta") && 644 !nvram_match(strcat_r(prefix, "mode", tmp2), "psr")) 645 goto PSTA_ERR; 646 647 name = nvram_safe_get(strcat_r(prefix, "ifname", tmp)); 648 649 if (wl_ioctl(name, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) != 0) 650 goto PSTA_ERR; 651 else if (!memcmp(&bssid, bssid_null, 6)) 652 goto PSTA_ERR; 653 654 /* buffers and length */ 655 mac_list_size = sizeof(mac_list->count) + MAX_STA_COUNT * sizeof(struct ether_addr); 656 mac_list = malloc(mac_list_size); 657 658 if (!mac_list) 659 goto PSTA_ERR; 660 661 /* query wl for authenticated sta list */ 662 strcpy((char*)mac_list, "authe_sta_list"); 663 if (wl_ioctl(name, WLC_GET_VAR, mac_list, mac_list_size)) { 664 free(mac_list); 665 goto PSTA_ERR; 666 } 667 668 /* query sta_info for each STA and output one table row each */ 669 if (mac_list->count) 670 { 671 if (nvram_match(strcat_r(prefix, "akm", tmp), "")) 672 psta = 1; 673 else 674 for (i = 0; i < mac_list->count; i++) { 675 if (wl_autho(name, &mac_list->ea[i])) 676 { 677 psta = 1; 678 break; 679 } 680 } 681 } 682 683PSTA_ERR: 684 if (psta) 685 { 686 count_bss_down = 0; 687 ether_etoa((const unsigned char *) &bssid, macaddr); 688 if (psta_debug) dbg("psta send keepalive nulldata to %s\n", macaddr); 689 eval("wl", "-i", name, "send_nulldata", macaddr); 690#ifdef PSTA_DEBUG 691 count = (count + 1) % 10; 692 if (!count) check_wl_rate(name); 693#endif 694 } 695 else 696 { 697 if (psta_debug) dbg("psta disconnected\n"); 698 if (++count_bss_down > 9) 699 { 700 count_bss_down = 0; 701 if (wl_scan(unit)) 702 { 703 eval("wlconf", name, "down"); 704 eval("wlconf", name, "up"); 705 eval("wlconf", name, "start"); 706 } 707 } 708 else 709 { 710 eval("wl", "-i", name, "bss", "down"); 711 eval("wl", "-i", name, "down"); 712 eval("wl", "-i", name, "up"); 713 eval("wl", "-i", name, "bss", "up"); 714 } 715 } 716 717 if (mac_list) free(mac_list); 718} 719 720static void 721psta_monitor(int sig) 722{ 723 if (sig == SIGALRM) 724 { 725 psta_keepalive(0); 726#ifdef PXYSTA_DUALBAND 727 if (!nvram_match("dpsta_ifnames", "")) 728 psta_keepalive(1); 729#endif 730 alarm(NORMAL_PERIOD); 731 } 732} 733 734static void 735psta_monitor_exit(int sig) 736{ 737 if (sig == SIGTERM) 738 { 739 alarmtimer(0, 0); 740 remove("/var/run/psta_monitor.pid"); 741 exit(0); 742 } 743} 744 745int 746psta_monitor_main(int argc, char *argv[]) 747{ 748 FILE *fp; 749 sigset_t sigs_to_catch; 750 751 if (!psta_exist() && !psr_exist()) 752 return 0; 753#ifdef RTCONFIG_QTN 754 if (nvram_get_int("wlc_band") == 1) 755 return 0; 756#endif 757 /* write pid */ 758 if ((fp = fopen("/var/run/psta_monitor.pid", "w")) != NULL) 759 { 760 fprintf(fp, "%d", getpid()); 761 fclose(fp); 762 } 763 764 if (nvram_match("psta_debug", "1")) 765 psta_debug = 1; 766 767 /* set the signal handler */ 768 sigemptyset(&sigs_to_catch); 769 sigaddset(&sigs_to_catch, SIGALRM); 770 sigaddset(&sigs_to_catch, SIGTERM); 771 sigprocmask(SIG_UNBLOCK, &sigs_to_catch, NULL); 772 773 signal(SIGALRM, psta_monitor); 774 signal(SIGTERM, psta_monitor_exit); 775 776 /* turn off wireless led of other bands under psta mode */ 777 if (is_psta(nvram_get_int("wlc_band"))) 778 setWlOffLed(); 779 780 alarm(NORMAL_PERIOD); 781 782 /* Most of time it goes to sleep */ 783 while (1) 784 { 785 pause(); 786 } 787 788 return 0; 789} 790#endif 791#endif 792