SoftapController.cpp revision fe15b63d9def3721bb0ee4d2fa36c6f4d0daf8aa
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <errno.h> 19#include <fcntl.h> 20#include <string.h> 21 22#include <sys/socket.h> 23#include <sys/stat.h> 24#include <sys/ioctl.h> 25#include <sys/types.h> 26#include <sys/wait.h> 27 28#include <netinet/in.h> 29#include <arpa/inet.h> 30 31#include <linux/wireless.h> 32 33#include <openssl/evp.h> 34#include <openssl/sha.h> 35 36#define LOG_TAG "SoftapController" 37#include <cutils/log.h> 38#include "wifi.h" 39 40#include "SoftapController.h" 41 42SoftapController::SoftapController() { 43 mPid = 0; 44 mSock = socket(AF_INET, SOCK_DGRAM, 0); 45 if (mSock < 0) 46 LOGE("Failed to open socket"); 47 memset(mIface, 0, sizeof(mIface)); 48} 49 50SoftapController::~SoftapController() { 51 if (mSock >= 0) 52 close(mSock); 53} 54 55int SoftapController::setCommand(char *iface, const char *fname, unsigned buflen) { 56 char tBuf[SOFTAP_MAX_BUFFER_SIZE]; 57 struct iwreq wrq; 58 struct iw_priv_args *priv_ptr; 59 int i, j, ret; 60 int cmd = 0, sub_cmd = 0; 61 62 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name)); 63 wrq.u.data.pointer = tBuf; 64 wrq.u.data.length = sizeof(tBuf) / sizeof(struct iw_priv_args); 65 wrq.u.data.flags = 0; 66 if ((ret = ioctl(mSock, SIOCGIWPRIV, &wrq)) < 0) { 67 LOGE("SIOCGIPRIV failed: %d", ret); 68 return ret; 69 } 70 71 priv_ptr = (struct iw_priv_args *)wrq.u.data.pointer; 72 for(i=0; i < wrq.u.data.length;i++) { 73 if (strcmp(priv_ptr[i].name, fname) == 0) { 74 cmd = priv_ptr[i].cmd; 75 break; 76 } 77 } 78 79 if (i == wrq.u.data.length) { 80 LOGE("iface:%s, fname: %s - function not supported", iface, fname); 81 return -1; 82 } 83 84 if (cmd < SIOCDEVPRIVATE) { 85 for(j=0; j < i; j++) { 86 if ((priv_ptr[j].set_args == priv_ptr[i].set_args) && 87 (priv_ptr[j].get_args == priv_ptr[i].get_args) && 88 (priv_ptr[j].name[0] == '\0')) 89 break; 90 } 91 if (j == i) { 92 LOGE("iface:%s, fname: %s - invalid private ioctl", iface, fname); 93 return -1; 94 } 95 sub_cmd = cmd; 96 cmd = priv_ptr[j].cmd; 97 } 98 99 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name)); 100 if ((buflen == 0) && (*mBuf != 0)) 101 wrq.u.data.length = strlen(mBuf) + 1; 102 else 103 wrq.u.data.length = buflen; 104 wrq.u.data.pointer = mBuf; 105 wrq.u.data.flags = sub_cmd; 106 ret = ioctl(mSock, cmd, &wrq); 107 return ret; 108} 109 110int SoftapController::startDriver(char *iface) { 111 int ret; 112 113 if (mSock < 0) { 114 LOGE("Softap driver start - failed to open socket"); 115 return -1; 116 } 117 if (!iface || (iface[0] == '\0')) { 118 LOGD("Softap driver start - wrong interface"); 119 iface = mIface; 120 } 121 122 *mBuf = 0; 123 ret = setCommand(iface, "START"); 124 usleep(AP_DRIVER_START_DELAY); 125 LOGD("Softap driver start: %d", ret); 126 return ret; 127} 128 129int SoftapController::stopDriver(char *iface) { 130 int ret; 131 132 if (mSock < 0) { 133 LOGE("Softap driver stop - failed to open socket"); 134 return -1; 135 } 136 if (!iface || (iface[0] == '\0')) { 137 LOGD("Softap driver stop - wrong interface"); 138 iface = mIface; 139 } 140 *mBuf = 0; 141 ret = setCommand(iface, "STOP"); 142 LOGD("Softap driver stop: %d", ret); 143 return ret; 144} 145 146int SoftapController::startSoftap() { 147 pid_t pid = 1; 148 int ret = 0; 149 150 if (mPid) { 151 LOGE("Softap already started"); 152 return 0; 153 } 154 if (mSock < 0) { 155 LOGE("Softap startap - failed to open socket"); 156 return -1; 157 } 158#if 0 159 if ((pid = fork()) < 0) { 160 LOGE("fork failed (%s)", strerror(errno)); 161 return -1; 162 } 163#endif 164 /* system("iwpriv wl0.1 AP_BSS_START"); */ 165 if (!pid) { 166 /* start hostapd */ 167 return ret; 168 } else { 169 *mBuf = 0; 170 ret = setCommand(mIface, "AP_BSS_START"); 171 if (ret) { 172 LOGE("Softap startap - failed: %d", ret); 173 } 174 else { 175 mPid = pid; 176 LOGD("Softap startap - Ok"); 177 usleep(AP_BSS_START_DELAY); 178 } 179 } 180 return ret; 181 182} 183 184int SoftapController::stopSoftap() { 185 int ret; 186 187 if (mPid == 0) { 188 LOGE("Softap already stopped"); 189 return 0; 190 } 191 if (mSock < 0) { 192 LOGE("Softap stopap - failed to open socket"); 193 return -1; 194 } 195 *mBuf = 0; 196 ret = setCommand(mIface, "AP_BSS_STOP"); 197#if 0 198 LOGD("Stopping Softap service"); 199 kill(mPid, SIGTERM); 200 waitpid(mPid, NULL, 0); 201#endif 202 mPid = 0; 203 LOGD("Softap service stopped: %d", ret); 204 usleep(AP_BSS_STOP_DELAY); 205 return ret; 206} 207 208bool SoftapController::isSoftapStarted() { 209 return (mPid != 0 ? true : false); 210} 211 212int SoftapController::addParam(int pos, const char *cmd, const char *arg) 213{ 214 if (pos < 0) 215 return pos; 216 if ((unsigned)(pos + strlen(cmd) + strlen(arg) + 1) >= sizeof(mBuf)) { 217 LOGE("Command line is too big"); 218 return -1; 219 } 220 pos += sprintf(&mBuf[pos], "%s=%s,", cmd, arg); 221 return pos; 222} 223 224/* 225 * Arguments: 226 * argv[2] - wlan interface 227 * argv[3] - softap interface 228 * argv[4] - SSID 229 * argv[5] - Security 230 * argv[6] - Key 231 * argv[7] - Channel 232 * argv[8] - Preamble 233 * argv[9] - Max SCB 234 */ 235int SoftapController::setSoftap(int argc, char *argv[]) { 236 unsigned char psk[SHA256_DIGEST_LENGTH]; 237 char psk_str[2*SHA256_DIGEST_LENGTH+1]; 238 int ret, i = 0; 239 char *ssid, *iface; 240 241 if (mSock < 0) { 242 LOGE("Softap set - failed to open socket"); 243 return -1; 244 } 245 if (argc < 4) { 246 LOGE("Softap set - missing arguments"); 247 return -1; 248 } 249 250 strncpy(mIface, argv[3], sizeof(mIface)); 251 iface = argv[2]; 252 253 /* Create command line */ 254 i = addParam(i, "ASCII_CMD", "AP_CFG"); 255 if (argc > 4) { 256 ssid = argv[4]; 257 } else { 258 ssid = (char *)"AndroidAP"; 259 } 260 i = addParam(i, "SSID", ssid); 261 if (argc > 5) { 262 i = addParam(i, "SEC", argv[5]); 263 } else { 264 i = addParam(i, "SEC", "open"); 265 } 266 if (argc > 6) { 267 int j; 268 // Use the PKCS#5 PBKDF2 with 4096 iterations 269 PKCS5_PBKDF2_HMAC_SHA1(argv[6], strlen(argv[6]), 270 reinterpret_cast<const unsigned char *>(ssid), strlen(ssid), 271 4096, SHA256_DIGEST_LENGTH, psk); 272 for (j=0; j < SHA256_DIGEST_LENGTH; j++) { 273 sprintf(&psk_str[j<<1], "%02x", psk[j]); 274 } 275 psk_str[j<<1] = '\0'; 276 i = addParam(i, "KEY", psk_str); 277 } else { 278 i = addParam(i, "KEY", "12345678"); 279 } 280 if (argc > 7) { 281 i = addParam(i, "CHANNEL", argv[7]); 282 } else { 283 i = addParam(i, "CHANNEL", "6"); 284 } 285 if (argc > 8) { 286 i = addParam(i, "PREAMBLE", argv[8]); 287 } else { 288 i = addParam(i, "PREAMBLE", "0"); 289 } 290 if (argc > 9) { 291 i = addParam(i, "MAX_SCB", argv[9]); 292 } else { 293 i = addParam(i, "MAX_SCB", "8"); 294 } 295 if ((i < 0) || ((unsigned)(i + 4) >= sizeof(mBuf))) { 296 LOGE("Softap set - command is too big"); 297 return i; 298 } 299 sprintf(&mBuf[i], "END"); 300 301 /* system("iwpriv eth0 WL_AP_CFG ASCII_CMD=AP_CFG,SSID=\"AndroidAP\",SEC=\"open\",KEY=12345,CHANNEL=1,PREAMBLE=0,MAX_SCB=8,END"); */ 302 ret = setCommand(iface, "AP_SET_CFG"); 303 if (ret) { 304 LOGE("Softap set - failed: %d", ret); 305 } 306 else { 307 LOGD("Softap set - Ok"); 308 usleep(AP_SET_CFG_DELAY); 309 } 310 return ret; 311} 312 313/* 314 * Arguments: 315 * argv[2] - interface name 316 * argv[3] - AP or STA 317 */ 318int SoftapController::fwReloadSoftap(int argc, char *argv[]) 319{ 320 int ret, i = 0; 321 char *iface; 322 char *fwpath; 323 324 if (mSock < 0) { 325 LOGE("Softap fwrealod - failed to open socket"); 326 return -1; 327 } 328 if (argc < 4) { 329 LOGE("Softap fwreload - missing arguments"); 330 return -1; 331 } 332 333 iface = argv[2]; 334 335 if (strcmp(argv[3], "AP") == 0) { 336 fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP); 337 } else { 338 fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA); 339 } 340 if (!fwpath) 341 return -1; 342 sprintf(mBuf, "FW_PATH=%s", fwpath); 343 ret = setCommand(iface, "WL_FW_RELOAD"); 344 if (ret) { 345 LOGE("Softap fwReload - failed: %d", ret); 346 } 347 else { 348 LOGD("Softap fwReload - Ok"); 349 } 350 return ret; 351} 352 353int SoftapController::clientsSoftap(char **retbuf) 354{ 355 int ret; 356 357 if (mSock < 0) { 358 LOGE("Softap clients - failed to open socket"); 359 return -1; 360 } 361 *mBuf = 0; 362 ret = setCommand(mIface, "AP_GET_STA_LIST", SOFTAP_MAX_BUFFER_SIZE); 363 if (ret) { 364 LOGE("Softap clients - failed: %d", ret); 365 } else { 366 asprintf(retbuf, "Softap clients:%s", mBuf); 367 LOGD("Softap clients:%s", mBuf); 368 } 369 return ret; 370} 371