blob: 42f7010b018bbe14b86e58f9bbf24f644dd9d6e6 [file] [log] [blame]
Dmitry Shmidt5af38c32010-02-10 11:10:39 -08001/*
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
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080029#include <linux/wireless.h>
30
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080031#define LOG_TAG "SoftapController"
32#include <cutils/log.h>
33
34#include "SoftapController.h"
Dmitry Shmidt321f95a2010-03-09 15:46:34 -080035#include "sha1.h"
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080036
37SoftapController::SoftapController() {
38 mPid = 0;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080039 mSock = socket(AF_INET, SOCK_DGRAM, 0);
40 if (mSock < 0)
41 LOGE("Failed to open socket");
42 memset(mIface, 0, sizeof(mIface));
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080043}
44
45SoftapController::~SoftapController() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080046 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;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080064 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;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080069}
70
Dmitry Shmidtc3539e22010-03-12 14:16:46 -080071int SoftapController::startDriver(char *iface) {
72 struct iwreq wrq;
73 int fnum, ret;
74
75 if (mSock < 0) {
76 LOGE("Softap start - failed to open socket");
77 return -1;
78 }
79 if (!iface || (iface[0] == '\0')) {
80 LOGD("Softap start - wrong interface");
81 iface = mIface;
82 }
83 fnum = getPrivFuncNum(iface, "START");
84 if (fnum < 0) {
85 LOGE("Softap start - function not supported");
86 return -1;
87 }
88 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
89 wrq.u.data.length = 0;
90 wrq.u.data.pointer = mBuf;
91 wrq.u.data.flags = 0;
92 ret = ioctl(mSock, fnum, &wrq);
93 LOGD("Softap start: %d", ret);
94 return ret;
95}
96
97int SoftapController::stopDriver(char *iface) {
98 struct iwreq wrq;
99 int fnum, ret;
100
101 if (mSock < 0) {
102 LOGE("Softap stop - failed to open socket");
103 return -1;
104 }
105 if (!iface || (iface[0] == '\0')) {
106 LOGD("Softap start - wrong interface");
107 iface = mIface;
108 }
109 fnum = getPrivFuncNum(iface, "STOP");
110 if (fnum < 0) {
111 LOGE("Softap stop - function not supported");
112 return -1;
113 }
114 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
115 wrq.u.data.length = 0;
116 wrq.u.data.pointer = mBuf;
117 wrq.u.data.flags = 0;
118 ret = ioctl(mSock, fnum, &wrq);
119 LOGD("Softap stop: %d", ret);
120 return ret;
121}
122
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800123int SoftapController::startSoftap() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800124 struct iwreq wrq;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800125 pid_t pid = 1;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800126 int fnum, ret = 0;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800127
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800128 if (mPid) {
129 LOGE("Softap already started");
130 errno = EBUSY;
131 return -1;
132 }
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800133 if (mSock < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800134 LOGE("Softap startap - failed to open socket");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800135 return -1;
136 }
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800137#if 0
138 if ((pid = fork()) < 0) {
139 LOGE("fork failed (%s)", strerror(errno));
140 return -1;
141 }
142#endif
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800143 /* system("iwpriv wl0.1 AP_BSS_START"); */
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800144 if (!pid) {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800145 /* start hostapd */
146 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800147 } else {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800148 fnum = getPrivFuncNum(mIface, "AP_BSS_START");
149 if (fnum < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800150 LOGE("Softap startap - function not supported");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800151 return -1;
152 }
153 strncpy(wrq.ifr_name, mIface, sizeof(wrq.ifr_name));
154 wrq.u.data.length = 0;
155 wrq.u.data.pointer = mBuf;
156 wrq.u.data.flags = 0;
157 ret = ioctl(mSock, fnum, &wrq);
158 if (ret) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800159 LOGE("Softap startap - failed: %d", ret);
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800160 }
161 else {
162 mPid = pid;
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800163 LOGD("Softap startap - Ok");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800164 }
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800165 }
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800166 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800167
168}
169
170int SoftapController::stopSoftap() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800171 struct iwreq wrq;
172 int fnum, ret;
173
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800174 if (mPid == 0) {
175 LOGE("Softap already stopped");
176 return 0;
177 }
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800178 if (mSock < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800179 LOGE("Softap stopap - failed to open socket");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800180 return -1;
181 }
Dmitry Shmidt9178b732010-03-12 13:04:09 -0800182 fnum = getPrivFuncNum(mIface, "AP_BSS_STOP");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800183 if (fnum < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800184 LOGE("Softap stopap - function not supported");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800185 return -1;
186 }
187 strncpy(wrq.ifr_name, mIface, sizeof(wrq.ifr_name));
188 wrq.u.data.length = 0;
189 wrq.u.data.pointer = mBuf;
190 wrq.u.data.flags = 0;
191 ret = ioctl(mSock, fnum, &wrq);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800192#if 0
193 LOGD("Stopping Softap service");
194 kill(mPid, SIGTERM);
195 waitpid(mPid, NULL, 0);
196#endif
197 mPid = 0;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800198 LOGD("Softap service stopped: %d", ret);
199 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800200}
201
202bool SoftapController::isSoftapStarted() {
203 return (mPid != 0 ? true : false);
204}
205
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800206int SoftapController::addParam(int pos, const char *cmd, const char *arg)
207{
208 if (pos < 0)
209 return pos;
210 if ((unsigned)(pos + strlen(cmd) + strlen(arg) + 1) >= sizeof(mBuf)) {
211 LOGE("Command line is too big");
212 return -1;
213 }
214 pos += sprintf(&mBuf[pos], "%s=%s,", cmd, arg);
215 return pos;
216}
217
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800218/*
219 * Arguments:
220 * argv[2] - wlan interface
221 * argv[3] - softap interface
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800222 * argv[4] - SSID
223 * argv[5] - Security
224 * argv[6] - Key
225 * argv[7] - Channel
226 * argv[8] - Preamble
227 * argv[9] - Max SCB
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800228 */
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800229int SoftapController::setSoftap(int argc, char *argv[]) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800230 unsigned char psk[MAX_SHA1_LEN];
231 char psk_str[2*MAX_SHA1_LEN+1];
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800232 struct iwreq wrq;
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800233 int fnum, ret, i = 0;
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800234 char *ssid;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800235
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800236 if (mSock < 0) {
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800237 LOGE("Softap set - failed to open socket");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800238 return -1;
239 }
240 if (argc < 4) {
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800241 LOGE("Softap set - missing arguments");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800242 return -1;
243 }
244
Dmitry Shmidt9178b732010-03-12 13:04:09 -0800245 fnum = getPrivFuncNum(argv[2], "AP_SET_CFG");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800246 if (fnum < 0) {
247 LOGE("Softap set - function not supported");
248 return -1;
249 }
250
251 strncpy(mIface, argv[3], sizeof(mIface));
252 strncpy(wrq.ifr_name, argv[2], sizeof(wrq.ifr_name));
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800253
254 /* Create command line */
255 i = addParam(i, "ASCII_CMD", "AP_CFG");
256 if (argc > 4) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800257 ssid = argv[4];
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800258 } else {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800259 ssid = (char *)"AndroidAP";
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800260 }
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800261 i = addParam(i, "SSID", ssid);
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800262 if (argc > 5) {
263 i = addParam(i, "SEC", argv[5]);
264 } else {
265 i = addParam(i, "SEC", "open");
266 }
267 if (argc > 6) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800268 int j;
269 pbkdf2_sha1(argv[6], ssid, strlen(ssid), 4096, psk, MAX_SHA1_LEN);
270 for(j=0;(j < MAX_SHA1_LEN);j++) {
271 sprintf(&psk_str[j<<1], "%02x", psk[j]);
272 }
273 psk_str[j<<1] = '\0';
274 i = addParam(i, "KEY", psk_str);
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800275 } else {
276 i = addParam(i, "KEY", "12345678");
277 }
278 if (argc > 7) {
279 i = addParam(i, "CHANNEL", argv[7]);
280 } else {
281 i = addParam(i, "CHANNEL", "6");
282 }
283 if (argc > 8) {
284 i = addParam(i, "PREAMBLE", argv[8]);
285 } else {
286 i = addParam(i, "PREAMBLE", "0");
287 }
288 if (argc > 9) {
289 i = addParam(i, "MAX_SCB", argv[9]);
290 } else {
291 i = addParam(i, "MAX_SCB", "8");
292 }
293 if ((i < 0) || ((unsigned)(i + 4) >= sizeof(mBuf))) {
294 LOGE("Softap set - command is too big");
295 return i;
296 }
297 sprintf(&mBuf[i], "END");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800298
299 wrq.u.data.length = strlen(mBuf) + 1;
300 wrq.u.data.pointer = mBuf;
301 wrq.u.data.flags = 0;
302 /* system("iwpriv eth0 WL_AP_CFG ASCII_CMD=AP_CFG,SSID=\"AndroidAP\",SEC=\"open\",KEY=12345,CHANNEL=1,PREAMBLE=0,MAX_SCB=8,END"); */
303 ret = ioctl(mSock, fnum, &wrq);
304 if (ret) {
305 LOGE("Softap set - failed: %d", ret);
306 }
307 else {
308 LOGD("Softap set - Ok");
309 }
310 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800311}
Dmitry Shmidt31fd6c52010-03-12 10:01:58 -0800312
313/*
314 * Arguments:
315 * argv[2] - interface name
316 * argv[3] - AP or STA
317 */
318int SoftapController::fwReloadSoftap(int argc, char *argv[])
319{
320 struct iwreq wrq;
321 int fnum, ret, i = 0;
322 char *iface;
323
324 if (mSock < 0) {
325 LOGE("Softap fwrealod - failed to open socket");
326 return -1;
327 }
328 if (argc < 4) {
329 LOGE("Softap fwreload - missing arguments");
330 return -1;
331 }
332
333 iface = argv[2];
334 fnum = getPrivFuncNum(iface, "WL_FW_RELOAD");
335 if (fnum < 0) {
336 LOGE("Softap fwReload - function not supported");
337 return -1;
338 }
339
340 if (strcmp(argv[3], "AP") == 0) {
341#ifdef WIFI_DRIVER_FW_AP_PATH
342 sprintf(mBuf, "FW_PATH=%s", WIFI_DRIVER_FW_AP_PATH);
343#endif
344 } else {
345#ifdef WIFI_DRIVER_FW_STA_PATH
346 sprintf(mBuf, "FW_PATH=%s", WIFI_DRIVER_FW_STA_PATH);
347#endif
348 }
349 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
350 wrq.u.data.length = strlen(mBuf) + 1;
351 wrq.u.data.pointer = mBuf;
352 wrq.u.data.flags = 0;
353 ret = ioctl(mSock, fnum, &wrq);
354 if (ret) {
355 LOGE("Softap fwReload - failed: %d", ret);
356 }
357 else {
358 LOGD("Softap fwReload - Ok");
359 }
360 return ret;
361}