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