1/* 2 * Miscellaneous services 3 * 4 * Copyright (C) 2009, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: services.c,v 1.100 2010/03/04 09:39:18 Exp $ 19 */ 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <unistd.h> 25#include <errno.h> 26#include <sys/time.h> 27#include <time.h> 28#include <bcmnvram.h> 29#include <shutils.h> 30#include <dirent.h> 31#include <sys/mount.h> 32#include <sys/vfs.h> 33#include <rc.h> 34#include <shared.h> 35#include <arpa/inet.h> 36#include <time.h> 37#include <sys/time.h> 38#include <errno.h> 39#include <security_ipc.h> 40#include <bcmutils.h> 41#include <wlutils.h> 42#include <wlscan.h> 43#ifdef RTCONFIG_WPS 44#include <wps_ui.h> 45#endif 46 47#ifdef RTCONFIG_QTN 48#include "web-qtn.h" 49#endif 50 51static int 52set_wps_env(char *uibuf) 53{ 54 int wps_fd = -1; 55 struct sockaddr_in to; 56 int sentBytes = 0; 57 uint32 uilen = strlen(uibuf); 58 59 //if (is_wps_enabled() == 0) 60 // return -1; 61 62 if ((wps_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 63 goto exit; 64 } 65 66 /* send to WPS */ 67 to.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 68 to.sin_family = AF_INET; 69 to.sin_port = htons(WPS_UI_PORT); 70 71 sentBytes = sendto(wps_fd, uibuf, uilen, 0, (struct sockaddr *) &to, 72 sizeof(struct sockaddr_in)); 73 74 if (sentBytes != uilen) { 75 goto exit; 76 } 77 78 /* Sleep 100 ms to make sure 79 WPS have received socket */ 80 usleep(100*1000); 81 close(wps_fd); 82 return 0; 83 84exit: 85 if (wps_fd >= 0) 86 close(wps_fd); 87 88 /* Show error message ? */ 89 return -1; 90} 91 92 93 94/* 95 * input variables: 96 * nvram: wps_band: 97 * nvram: wps_action: WPS_UI_ACT_ADDENROLLEE/WPS_UI_ACT_CONFIGAe 98 * (wps_method: (according to wps_sta_pin) 99 * nvram: wps_sta_pin: 100 * nvram: wps_version2: 101 * nvram: wps_autho_sta_mac: 102 * 103 * output variables: 104 * wps_proc_status 105 */ 106 107int 108start_wps_method(void) 109{ 110 int wps_band; 111 int wps_action; 112// int wps_method; 113 char *wps_sta_pin; 114 char prefix[]="wlXXXXXX_", tmp[100]; 115 char buf[256] = "SET "; 116 int len = 4; 117 118 if (getpid()!=1) { 119 notify_rc("start_wps_method"); 120 return 0; 121 } 122 123 wps_band = nvram_get_int("wps_band"); 124 snprintf(prefix, sizeof(prefix), "wl%d_", wps_band); 125 wps_action = nvram_get_int("wps_action"); 126// wps_method = nvram_get_int("wps_method"); // useless 127 wps_sta_pin = nvram_safe_get("wps_sta_pin"); 128 129#ifdef RTCONFIG_QTN 130 int retval; 131 132#ifdef RTCONFIG_WPS_DUALBAND 133 if (1) 134#else 135 if (wps_band) 136#endif 137 { 138 if (strlen(wps_sta_pin) && strcmp(wps_sta_pin, "00000000") && (wl_wpsPincheck(wps_sta_pin) == 0)) 139 { 140 retval = rpc_qcsapi_wps_registrar_report_pin(WIFINAME, wps_sta_pin); 141 if (retval < 0) 142 dbG("rpc_qcsapi_wps_registrar_report_pin %s error, return: %d\n", WIFINAME, retval); 143 } 144 else 145 { 146 retval = rpc_qcsapi_wps_registrar_report_button_press(WIFINAME); 147 if (retval < 0) 148 dbG("rpc_qcsapi_wps_registrar_report_button_press %s error, return: %d\n", WIFINAME, retval); 149 } 150 151#ifdef RTCONFIG_WPS_DUALBAND 152 // return 0; 153#else 154 return 0; 155#endif 156 } 157#endif 158 159 if (strlen(wps_sta_pin) && strcmp(wps_sta_pin, "00000000") && (wl_wpsPincheck(wps_sta_pin) == 0)) 160 len += sprintf(buf + len, "wps_method=%d ", WPS_UI_METHOD_PIN); 161 else 162 len += sprintf(buf + len, "wps_method=%d ", WPS_UI_METHOD_PBC); 163 164 if (nvram_match("wps_version2", "enabled") && strlen(nvram_safe_get("wps_autho_sta_mac"))) 165 len += sprintf(buf + len, "wps_autho_sta_mac=%s ", nvram_safe_get("wps_autho_sta_mac")); 166 167 if (strlen(wps_sta_pin)) 168 len += sprintf(buf + len, "wps_sta_pin=%s ", wps_sta_pin); 169 else 170 len += sprintf(buf + len, "wps_sta_pin=00000000 "); 171 172// len += sprintf(buf + len, "wps_action=%d ", wps_action); 173 len += sprintf(buf + len, "wps_action=%d ", WPS_UI_ACT_ADDENROLLEE); 174 175 len += sprintf(buf + len, "wps_config_command=%d ", WPS_UI_CMD_START); 176 177 nvram_set("wps_proc_status", "0"); 178 179 len += sprintf(buf + len, "wps_pbc_method=%d ", WPS_UI_PBC_SW); 180 len += sprintf(buf + len, "wps_ifname=%s ", nvram_safe_get(strcat_r(prefix, "ifname", tmp))); 181 182 dbG("wps env buffer: %s\n", buf); 183 184// nvram_unset("wps_sta_devname"); 185// nvram_unset("wps_sta_mac"); 186// nvram_unset("wps_pinfail"); 187// nvram_unset("wps_pinfail_mac"); 188// nvram_unset("wps_pinfail_name"); 189// nvram_unset("wps_pinfail_state"); 190 191 nvram_set("wps_env_buf", buf); 192 nvram_set_int("wps_restart_war", 1); 193 set_wps_env(buf); 194 195 sprintf(tmp, "%lu", uptime()); 196 nvram_set("wps_uptime", tmp); 197 198 return 0; 199} 200 201void 202restart_wps_monitor(void) 203{ 204 int unit; 205 char word[256], *next; 206 char tmp[100], prefix[]="wlXXXXXXX_"; 207 char *wps_argv[] = {"/bin/wps_monitor", NULL}; 208 pid_t pid; 209 210 unlink("/tmp/wps_monitor.pid"); 211 212 if (nvram_match("wps_enable", "1")) 213 { 214 unit = 0; 215 foreach(word, nvram_safe_get("wl_ifnames"), next) 216 { 217 snprintf(prefix, sizeof(prefix), "wl%d_", unit); 218 nvram_set(strcat_r(prefix, "wps_mode", tmp), "enabled"); 219 220 unit++; 221 } 222 223 killall_tk("wps_monitor"); 224 225 _eval(wps_argv, NULL, 0, &pid); 226 } 227} 228 229int 230stop_wps_method(void) 231{ 232 char buf[256] = "SET "; 233 int len = 4; 234 235 if (getpid()!=1) { 236 notify_rc("stop_wps_method"); 237 return 0; 238 } 239 240#ifdef RTCONFIG_QTN 241 int retval = rpc_qcsapi_wps_cancel(WIFINAME); 242 if (retval < 0) 243 dbG("rpc_qcsapi_wps_cancel %s error, return: %d\n", WIFINAME, retval); 244#endif 245 246 len += sprintf(buf + len, "wps_config_command=%d ", WPS_UI_CMD_STOP); 247 len += sprintf(buf + len, "wps_action=%d ", WPS_UI_ACT_NONE); 248 249 set_wps_env(buf); 250 251 usleep(100*1000); 252 253 int status = nvram_get_int("wps_proc_status"); 254 if (status != 2 && status != 7) 255 restart_wps_monitor(); 256 257 return 0; 258} 259 260int is_wps_stopped(void) 261{ 262 int ret = 1; 263#ifdef RTCONFIG_QTN 264#ifdef RTCONFIG_WPS_DUALBAND 265 int ret_qtn = 1; 266#endif 267#endif 268 int status = nvram_get_int("wps_proc_status"); 269 time_t now = uptime(); 270 time_t wps_uptime = strtoul(nvram_safe_get("wps_uptime"), NULL, 10); 271 char tmp[100]; 272 273 if ((now - wps_uptime) < 2) 274 return 0; 275 276#ifdef RTCONFIG_QTN 277 char wps_state[32], state_str[32]; 278 int retval, state = -1 ; 279 280#ifdef RTCONFIG_WPS_DUALBAND 281 if (nvram_get_int("wps_enable")) 282#else 283 if (nvram_get_int("wps_enable") && nvram_get_int("wps_band")) 284#endif 285 { 286 retval = rpc_qcsapi_wps_get_state(WIFINAME, wps_state, sizeof(wps_state)); 287 if (retval < 0) 288 dbG("rpc_qcsapi_wps_get_state %s error, return: %d\n", WIFINAME, retval); 289 else 290 { 291 if (sscanf(wps_state, "%d %s", &state, state_str) != 2) 292 dbG("prase wps state error!\n"); 293 294 switch (state) { 295 case 0: /* WPS_INITIAL */ 296 dbg("QTN: WPS Init\n"); 297 break; 298 case 1: /* WPS_START */ 299 dbg("QTN: Processing WPS start...\n"); 300 ret = 0; 301#ifdef RTCONFIG_WPS_DUALBAND 302 ret_qtn = 0; 303#endif 304 break; 305 case 2: /* WPS_SUCCESS */ 306 dbg("QTN: WPS Success\n"); 307 break; 308 case 3: /* WPS_ERROR */ 309 dbg("QTN: WPS Fail due to message exange error!\n"); 310 break; 311 case 4: /* WPS_TIMEOUT */ 312 dbg("QTN: WPS Fail due to time out!\n"); 313 break; 314 case 5: /* WPS_OVERLAP */ 315 dbg("QTN: WPS Fail due to PBC session overlap!\n"); 316 break; 317 default: 318 ret = 0; 319#ifdef RTCONFIG_WPS_DUALBAND 320 ret_qtn = 0; 321#endif 322 break; 323 } 324 } 325 326#ifdef RTCONFIG_WPS_DUALBAND 327 // return ret; 328#else 329 return ret; 330#endif 331 } 332#endif 333 334 switch (status) { 335 case 0: /* Init */ 336 dbg("Init again?\n"); 337 if (nvram_get_int("wps_restart_war") && (now - wps_uptime) < 3) 338 { 339 dbg("Re-send WPS env!!!\n"); 340 set_wps_env(nvram_safe_get("wps_env_buf")); 341 nvram_unset("wps_env_buf"); 342 nvram_set_int("wps_restart_war", 0); 343 sprintf(tmp, "%lu", uptime()); 344 nvram_set("wps_uptime", tmp); 345 return 0; 346 } 347 break; 348 case 1: /* WPS_ASSOCIATED */ 349 dbg("Processing WPS start...\n"); 350 ret = 0; 351 break; 352 case 2: /* WPS_OK */ 353 case 7: /* WPS_MSGDONE */ 354 dbg("WPS Success\n"); 355 break; 356 case 3: /* WPS_MSG_ERR */ 357 dbg("WPS Fail due to message exange error!\n"); 358 break; 359 case 4: /* WPS_TIMEOUT */ 360 dbg("WPS Fail due to time out!\n"); 361 break; 362 default: 363 ret = 0; 364 break; 365 } 366 367#ifdef RTCONFIG_WPS_DUALBAND 368 if(ret == 1 || ret_qtn == 1){ 369 nvram_set("wps_proc_status", "0"); 370 return 1; 371 }else{ 372 return 0; 373 } 374 // return ret; 375#else 376 return ret; 377#endif 378 // TODO: handle enrollee 379} 380