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