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