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