SoftapController.cpp revision 7977d67059ef94eefa9b14038df156b416fef877
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 36SoftapController::SoftapController() { 37 mPid = 0; 38 mSock = socket(AF_INET, SOCK_DGRAM, 0); 39 if (mSock < 0) 40 LOGE("Failed to open socket"); 41 memset(mIface, 0, sizeof(mIface)); 42} 43 44SoftapController::~SoftapController() { 45 if (mSock >= 0) 46 close(mSock); 47} 48 49int SoftapController::getPrivFuncNum(char *iface, const char *fname) { 50 struct iwreq wrq; 51 struct iw_priv_args *priv_ptr; 52 int i, ret; 53 54 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name)); 55 wrq.u.data.pointer = mBuf; 56 wrq.u.data.length = sizeof(mBuf) / sizeof(struct iw_priv_args); 57 wrq.u.data.flags = 0; 58 if ((ret = ioctl(mSock, SIOCGIWPRIV, &wrq)) < 0) { 59 LOGE("SIOCGIPRIV failed: %d", ret); 60 return ret; 61 } 62 priv_ptr = (struct iw_priv_args *)wrq.u.data.pointer; 63 for(i=0;(i < wrq.u.data.length);i++) { 64 if (strcmp(priv_ptr[i].name, fname) == 0) 65 return priv_ptr[i].cmd; 66 } 67 return -1; 68} 69 70int SoftapController::startSoftap() { 71 struct iwreq wrq; 72 pid_t pid = 1; 73 int fnum, ret = 0; 74 75 LOGD("Softap start"); 76 if (mPid) { 77 LOGE("Softap already started"); 78 errno = EBUSY; 79 return -1; 80 } 81 if (mSock < 0) { 82 LOGE("Failed to open socket"); 83 return -1; 84 } 85#if 0 86 if ((pid = fork()) < 0) { 87 LOGE("fork failed (%s)", strerror(errno)); 88 return -1; 89 } 90#endif 91 /* system("iwpriv wl0.1 AP_BSS_START"); */ 92 if (!pid) { 93 /* start hostapd */ 94 return ret; 95 } else { 96 fnum = getPrivFuncNum(mIface, "AP_BSS_START"); 97 if (fnum < 0) { 98 LOGE("Softap start - function not supported"); 99 return -1; 100 } 101 strncpy(wrq.ifr_name, mIface, sizeof(wrq.ifr_name)); 102 wrq.u.data.length = 0; 103 wrq.u.data.pointer = mBuf; 104 wrq.u.data.flags = 0; 105 ret = ioctl(mSock, fnum, &wrq); 106 if (ret) { 107 LOGE("Softap start - failed: %d", ret); 108 } 109 else { 110 mPid = pid; 111 LOGD("Softap start - Ok"); 112 } 113 } 114 return ret; 115 116} 117 118int SoftapController::stopSoftap() { 119 struct iwreq wrq; 120 int fnum, ret; 121 122 if (mPid == 0) { 123 LOGE("Softap already stopped"); 124 return 0; 125 } 126 if (mSock < 0) { 127 LOGE("Softap stop - failed to open socket"); 128 return -1; 129 } 130 fnum = getPrivFuncNum(mIface, "WL_AP_STOP"); 131 if (fnum < 0) { 132 LOGE("Softap stop - function not supported"); 133 return -1; 134 } 135 strncpy(wrq.ifr_name, mIface, sizeof(wrq.ifr_name)); 136 wrq.u.data.length = 0; 137 wrq.u.data.pointer = mBuf; 138 wrq.u.data.flags = 0; 139 ret = ioctl(mSock, fnum, &wrq); 140#if 0 141 LOGD("Stopping Softap service"); 142 kill(mPid, SIGTERM); 143 waitpid(mPid, NULL, 0); 144#endif 145 mPid = 0; 146 LOGD("Softap service stopped: %d", ret); 147 return ret; 148} 149 150bool SoftapController::isSoftapStarted() { 151 return (mPid != 0 ? true : false); 152} 153 154int SoftapController::addParam(int pos, const char *cmd, const char *arg) 155{ 156 if (pos < 0) 157 return pos; 158 if ((unsigned)(pos + strlen(cmd) + strlen(arg) + 1) >= sizeof(mBuf)) { 159 LOGE("Command line is too big"); 160 return -1; 161 } 162 pos += sprintf(&mBuf[pos], "%s=%s,", cmd, arg); 163 return pos; 164} 165 166/* 167 * Arguments: 168 * argv[2] - wlan interface 169 * argv[3] - softap interface 170 * argv[4] - SSID 171 * argv[5] - Security 172 * argv[6] - Key 173 * argv[7] - Channel 174 * argv[8] - Preamble 175 * argv[9] - Max SCB 176 */ 177int SoftapController::setSoftap(int argc, char *argv[]) { 178 struct iwreq wrq; 179 int fnum, ret, i = 0; 180 181 if (mSock < 0) { 182 LOGE("Softap set - failed to open socket"); 183 return -1; 184 } 185 if (argc < 4) { 186 LOGE("Softap set - missing arguments"); 187 return -1; 188 } 189 190 fnum = getPrivFuncNum(argv[2], "WL_AP_CFG"); 191 if (fnum < 0) { 192 LOGE("Softap set - function not supported"); 193 return -1; 194 } 195 196 strncpy(mIface, argv[3], sizeof(mIface)); 197 strncpy(wrq.ifr_name, argv[2], sizeof(wrq.ifr_name)); 198 199 /* Create command line */ 200 i = addParam(i, "ASCII_CMD", "AP_CFG"); 201 if (argc > 4) { 202 i = addParam(i, "SSID", argv[4]); 203 } else { 204 i = addParam(i, "SSID", "AndroidAP"); 205 } 206 if (argc > 5) { 207 i = addParam(i, "SEC", argv[5]); 208 } else { 209 i = addParam(i, "SEC", "open"); 210 } 211 if (argc > 6) { 212 i = addParam(i, "KEY", argv[6]); 213 } else { 214 i = addParam(i, "KEY", "12345678"); 215 } 216 if (argc > 7) { 217 i = addParam(i, "CHANNEL", argv[7]); 218 } else { 219 i = addParam(i, "CHANNEL", "6"); 220 } 221 if (argc > 8) { 222 i = addParam(i, "PREAMBLE", argv[8]); 223 } else { 224 i = addParam(i, "PREAMBLE", "0"); 225 } 226 if (argc > 9) { 227 i = addParam(i, "MAX_SCB", argv[9]); 228 } else { 229 i = addParam(i, "MAX_SCB", "8"); 230 } 231 if ((i < 0) || ((unsigned)(i + 4) >= sizeof(mBuf))) { 232 LOGE("Softap set - command is too big"); 233 return i; 234 } 235 sprintf(&mBuf[i], "END"); 236 237 wrq.u.data.length = strlen(mBuf) + 1; 238 wrq.u.data.pointer = mBuf; 239 wrq.u.data.flags = 0; 240 /* system("iwpriv eth0 WL_AP_CFG ASCII_CMD=AP_CFG,SSID=\"AndroidAP\",SEC=\"open\",KEY=12345,CHANNEL=1,PREAMBLE=0,MAX_SCB=8,END"); */ 241 ret = ioctl(mSock, fnum, &wrq); 242 if (ret) { 243 LOGE("Softap set - failed: %d", ret); 244 } 245 else { 246 LOGD("Softap set - Ok"); 247 } 248 return ret; 249} 250