blob: a68af22c003a735f22d00979e29ccf5587ac7b1e [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
Kenny Roota2d7e3e2010-03-15 14:26:36 -070031#include <openssl/evp.h>
32#include <openssl/sha.h>
33
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080034#define LOG_TAG "SoftapController"
35#include <cutils/log.h>
36
37#include "SoftapController.h"
38
39SoftapController::SoftapController() {
40 mPid = 0;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080041 mSock = socket(AF_INET, SOCK_DGRAM, 0);
42 if (mSock < 0)
43 LOGE("Failed to open socket");
44 memset(mIface, 0, sizeof(mIface));
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080045}
46
47SoftapController::~SoftapController() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080048 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;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080066 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;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080071}
72
Dmitry Shmidtc3539e22010-03-12 14:16:46 -080073int 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
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800125int SoftapController::startSoftap() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800126 struct iwreq wrq;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800127 pid_t pid = 1;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800128 int fnum, ret = 0;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800129
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800130 if (mPid) {
131 LOGE("Softap already started");
132 errno = EBUSY;
133 return -1;
134 }
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800135 if (mSock < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800136 LOGE("Softap startap - failed to open socket");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800137 return -1;
138 }
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800139#if 0
140 if ((pid = fork()) < 0) {
141 LOGE("fork failed (%s)", strerror(errno));
142 return -1;
143 }
144#endif
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800145 /* system("iwpriv wl0.1 AP_BSS_START"); */
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800146 if (!pid) {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800147 /* start hostapd */
148 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800149 } else {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800150 fnum = getPrivFuncNum(mIface, "AP_BSS_START");
151 if (fnum < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800152 LOGE("Softap startap - function not supported");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800153 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) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800161 LOGE("Softap startap - failed: %d", ret);
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800162 }
163 else {
164 mPid = pid;
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800165 LOGD("Softap startap - Ok");
Dmitry Shmidt3df450a2010-03-18 13:06:47 -0700166 usleep(AP_BSS_START_DELAY);
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800167 }
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800168 }
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800169 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800170
171}
172
173int SoftapController::stopSoftap() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800174 struct iwreq wrq;
175 int fnum, ret;
176
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800177 if (mPid == 0) {
178 LOGE("Softap already stopped");
179 return 0;
180 }
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800181 if (mSock < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800182 LOGE("Softap stopap - failed to open socket");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800183 return -1;
184 }
Dmitry Shmidt9178b732010-03-12 13:04:09 -0800185 fnum = getPrivFuncNum(mIface, "AP_BSS_STOP");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800186 if (fnum < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800187 LOGE("Softap stopap - function not supported");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800188 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);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800195#if 0
196 LOGD("Stopping Softap service");
197 kill(mPid, SIGTERM);
198 waitpid(mPid, NULL, 0);
199#endif
200 mPid = 0;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800201 LOGD("Softap service stopped: %d", ret);
Dmitry Shmidt3df450a2010-03-18 13:06:47 -0700202 usleep(AP_BSS_STOP_DELAY);
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800203 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800204}
205
206bool SoftapController::isSoftapStarted() {
207 return (mPid != 0 ? true : false);
208}
209
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800210int 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
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800222/*
223 * Arguments:
224 * argv[2] - wlan interface
225 * argv[3] - softap interface
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800226 * argv[4] - SSID
227 * argv[5] - Security
228 * argv[6] - Key
229 * argv[7] - Channel
230 * argv[8] - Preamble
231 * argv[9] - Max SCB
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800232 */
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800233int SoftapController::setSoftap(int argc, char *argv[]) {
Kenny Roota2d7e3e2010-03-15 14:26:36 -0700234 unsigned char psk[SHA256_DIGEST_LENGTH];
235 char psk_str[2*SHA256_DIGEST_LENGTH+1];
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800236 struct iwreq wrq;
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800237 int fnum, ret, i = 0;
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800238 char *ssid;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800239
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800240 if (mSock < 0) {
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800241 LOGE("Softap set - failed to open socket");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800242 return -1;
243 }
244 if (argc < 4) {
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800245 LOGE("Softap set - missing arguments");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800246 return -1;
247 }
248
Dmitry Shmidt9178b732010-03-12 13:04:09 -0800249 fnum = getPrivFuncNum(argv[2], "AP_SET_CFG");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800250 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));
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800257
258 /* Create command line */
259 i = addParam(i, "ASCII_CMD", "AP_CFG");
260 if (argc > 4) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800261 ssid = argv[4];
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800262 } else {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800263 ssid = (char *)"AndroidAP";
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800264 }
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800265 i = addParam(i, "SSID", ssid);
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800266 if (argc > 5) {
267 i = addParam(i, "SEC", argv[5]);
268 } else {
269 i = addParam(i, "SEC", "open");
270 }
271 if (argc > 6) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800272 int j;
Kenny Roota2d7e3e2010-03-15 14:26:36 -0700273 // 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++) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800278 sprintf(&psk_str[j<<1], "%02x", psk[j]);
279 }
280 psk_str[j<<1] = '\0';
281 i = addParam(i, "KEY", psk_str);
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800282 } 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");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800305
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");
Dmitry Shmidt3df450a2010-03-18 13:06:47 -0700316 usleep(AP_SET_CFG_DELAY);
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800317 }
318 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800319}
Dmitry Shmidt31fd6c52010-03-12 10:01:58 -0800320
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}