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 driver start - failed to open socket"); 79 return -1; 80 } 81 if (!iface || (iface[0] == '\0')) { 82 LOGD("Softap driver start - wrong interface"); 83 iface = mIface; 84 } 85 fnum = getPrivFuncNum(iface, "START"); 86 if (fnum < 0) { 87 LOGE("Softap driver 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 usleep(AP_DRIVER_START_DELAY); 96 LOGD("Softap driver start: %d", ret); 97 return ret; 98} 99 100int SoftapController::stopDriver(char *iface) { 101 struct iwreq wrq; 102 int fnum, ret; 103 104 if (mSock < 0) { 105 LOGE("Softap driver stop - failed to open socket"); 106 return -1; 107 } 108 if (!iface || (iface[0] == '\0')) { 109 LOGD("Softap driver stop - wrong interface"); 110 iface = mIface; 111 } 112 fnum = getPrivFuncNum(iface, "STOP"); 113 if (fnum < 0) { 114 LOGE("Softap driver stop - function not supported"); 115 return -1; 116 } 117 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name)); 118 wrq.u.data.length = 0; 119 wrq.u.data.pointer = mBuf; 120 wrq.u.data.flags = 0; 121 ret = ioctl(mSock, fnum, &wrq); 122 LOGD("Softap driver stop: %d", ret); 123 return ret; 124} 125 126int SoftapController::startSoftap() { 127 struct iwreq wrq; 128 pid_t pid = 1; 129 int fnum, ret = 0; 130 131 if (mPid) { 132 LOGE("Softap already started"); 133 return 0; 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 usleep(AP_BSS_START_DELAY); 167 } 168 } 169 return ret; 170 171} 172 173int SoftapController::stopSoftap() { 174 struct iwreq wrq; 175 int fnum, ret; 176 177 if (mPid == 0) { 178 LOGE("Softap already stopped"); 179 return 0; 180 } 181 if (mSock < 0) { 182 LOGE("Softap stopap - failed to open socket"); 183 return -1; 184 } 185 fnum = getPrivFuncNum(mIface, "AP_BSS_STOP"); 186 if (fnum < 0) { 187 LOGE("Softap stopap - function not supported"); 188 return -1; 189 } 190 strncpy(wrq.ifr_name, mIface, sizeof(wrq.ifr_name)); 191 wrq.u.data.length = 0; 192 wrq.u.data.pointer = mBuf; 193 wrq.u.data.flags = 0; 194 ret = ioctl(mSock, fnum, &wrq); 195#if 0 196 LOGD("Stopping Softap service"); 197 kill(mPid, SIGTERM); 198 waitpid(mPid, NULL, 0); 199#endif 200 mPid = 0; 201 LOGD("Softap service stopped: %d", ret); 202 usleep(AP_BSS_STOP_DELAY); 203 return ret; 204} 205 206bool SoftapController::isSoftapStarted() { 207 return (mPid != 0 ? true : false); 208} 209 210int SoftapController::addParam(int pos, const char *cmd, const char *arg) 211{ 212 if (pos < 0) 213 return pos; 214 if ((unsigned)(pos + strlen(cmd) + strlen(arg) + 1) >= sizeof(mBuf)) { 215 LOGE("Command line is too big"); 216 return -1; 217 } 218 pos += sprintf(&mBuf[pos], "%s=%s,", cmd, arg); 219 return pos; 220} 221 222/* 223 * Arguments: 224 * argv[2] - wlan interface 225 * argv[3] - softap interface 226 * argv[4] - SSID 227 * argv[5] - Security 228 * argv[6] - Key 229 * argv[7] - Channel 230 * argv[8] - Preamble 231 * argv[9] - Max SCB 232 */ 233int SoftapController::setSoftap(int argc, char *argv[]) { 234 unsigned char psk[SHA256_DIGEST_LENGTH]; 235 char psk_str[2*SHA256_DIGEST_LENGTH+1]; 236 struct iwreq wrq; 237 int fnum, ret, i = 0; 238 char *ssid; 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 fnum = getPrivFuncNum(argv[2], "AP_SET_CFG"); 250 if (fnum < 0) { 251 LOGE("Softap set - function not supported"); 252 return -1; 253 } 254 255 strncpy(mIface, argv[3], sizeof(mIface)); 256 strncpy(wrq.ifr_name, argv[2], sizeof(wrq.ifr_name)); 257 258 /* Create command line */ 259 i = addParam(i, "ASCII_CMD", "AP_CFG"); 260 if (argc > 4) { 261 ssid = argv[4]; 262 } else { 263 ssid = (char *)"AndroidAP"; 264 } 265 i = addParam(i, "SSID", ssid); 266 if (argc > 5) { 267 i = addParam(i, "SEC", argv[5]); 268 } else { 269 i = addParam(i, "SEC", "open"); 270 } 271 if (argc > 6) { 272 int j; 273 // Use the PKCS#5 PBKDF2 with 4096 iterations 274 PKCS5_PBKDF2_HMAC_SHA1(argv[6], strlen(argv[6]), 275 reinterpret_cast<const unsigned char *>(ssid), strlen(ssid), 276 4096, SHA256_DIGEST_LENGTH, psk); 277 for (j=0; j < SHA256_DIGEST_LENGTH; j++) { 278 sprintf(&psk_str[j<<1], "%02x", psk[j]); 279 } 280 psk_str[j<<1] = '\0'; 281 i = addParam(i, "KEY", psk_str); 282 } else { 283 i = addParam(i, "KEY", "12345678"); 284 } 285 if (argc > 7) { 286 i = addParam(i, "CHANNEL", argv[7]); 287 } else { 288 i = addParam(i, "CHANNEL", "6"); 289 } 290 if (argc > 8) { 291 i = addParam(i, "PREAMBLE", argv[8]); 292 } else { 293 i = addParam(i, "PREAMBLE", "0"); 294 } 295 if (argc > 9) { 296 i = addParam(i, "MAX_SCB", argv[9]); 297 } else { 298 i = addParam(i, "MAX_SCB", "8"); 299 } 300 if ((i < 0) || ((unsigned)(i + 4) >= sizeof(mBuf))) { 301 LOGE("Softap set - command is too big"); 302 return i; 303 } 304 sprintf(&mBuf[i], "END"); 305 306 wrq.u.data.length = strlen(mBuf) + 1; 307 wrq.u.data.pointer = mBuf; 308 wrq.u.data.flags = 0; 309 /* system("iwpriv eth0 WL_AP_CFG ASCII_CMD=AP_CFG,SSID=\"AndroidAP\",SEC=\"open\",KEY=12345,CHANNEL=1,PREAMBLE=0,MAX_SCB=8,END"); */ 310 ret = ioctl(mSock, fnum, &wrq); 311 if (ret) { 312 LOGE("Softap set - failed: %d", ret); 313 } 314 else { 315 LOGD("Softap set - Ok"); 316 usleep(AP_SET_CFG_DELAY); 317 } 318 return ret; 319} 320 321/* 322 * Arguments: 323 * argv[2] - interface name 324 * argv[3] - AP or STA 325 */ 326int SoftapController::fwReloadSoftap(int argc, char *argv[]) 327{ 328 struct iwreq wrq; 329 int fnum, ret, i = 0; 330 char *iface; 331 332 if (mSock < 0) { 333 LOGE("Softap fwrealod - failed to open socket"); 334 return -1; 335 } 336 if (argc < 4) { 337 LOGE("Softap fwreload - missing arguments"); 338 return -1; 339 } 340 341 iface = argv[2]; 342 fnum = getPrivFuncNum(iface, "WL_FW_RELOAD"); 343 if (fnum < 0) { 344 LOGE("Softap fwReload - function not supported"); 345 return -1; 346 } 347 348 if (strcmp(argv[3], "AP") == 0) { 349#ifdef WIFI_DRIVER_FW_AP_PATH 350 sprintf(mBuf, "FW_PATH=%s", WIFI_DRIVER_FW_AP_PATH); 351#endif 352 } else { 353#ifdef WIFI_DRIVER_FW_STA_PATH 354 sprintf(mBuf, "FW_PATH=%s", WIFI_DRIVER_FW_STA_PATH); 355#endif 356 } 357 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name)); 358 wrq.u.data.length = strlen(mBuf) + 1; 359 wrq.u.data.pointer = mBuf; 360 wrq.u.data.flags = 0; 361 ret = ioctl(mSock, fnum, &wrq); 362 if (ret) { 363 LOGE("Softap fwReload - failed: %d", ret); 364 } 365 else { 366 LOGD("Softap fwReload - Ok"); 367 } 368 return ret; 369} 370