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