blob: 6caa2476bddf1d1d5f06b3f0ad324335cdb78d4e [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 Shmidt84c65a62010-03-03 13:14:30 -0800166 }
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800167 }
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800168 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800169
170}
171
172int SoftapController::stopSoftap() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800173 struct iwreq wrq;
174 int fnum, ret;
175
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800176 if (mPid == 0) {
177 LOGE("Softap already stopped");
178 return 0;
179 }
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800180 if (mSock < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800181 LOGE("Softap stopap - failed to open socket");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800182 return -1;
183 }
Dmitry Shmidt9178b732010-03-12 13:04:09 -0800184 fnum = getPrivFuncNum(mIface, "AP_BSS_STOP");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800185 if (fnum < 0) {
Dmitry Shmidtc3539e22010-03-12 14:16:46 -0800186 LOGE("Softap stopap - function not supported");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800187 return -1;
188 }
189 strncpy(wrq.ifr_name, mIface, sizeof(wrq.ifr_name));
190 wrq.u.data.length = 0;
191 wrq.u.data.pointer = mBuf;
192 wrq.u.data.flags = 0;
193 ret = ioctl(mSock, fnum, &wrq);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800194#if 0
195 LOGD("Stopping Softap service");
196 kill(mPid, SIGTERM);
197 waitpid(mPid, NULL, 0);
198#endif
199 mPid = 0;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800200 LOGD("Softap service stopped: %d", ret);
201 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800202}
203
204bool SoftapController::isSoftapStarted() {
205 return (mPid != 0 ? true : false);
206}
207
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800208int SoftapController::addParam(int pos, const char *cmd, const char *arg)
209{
210 if (pos < 0)
211 return pos;
212 if ((unsigned)(pos + strlen(cmd) + strlen(arg) + 1) >= sizeof(mBuf)) {
213 LOGE("Command line is too big");
214 return -1;
215 }
216 pos += sprintf(&mBuf[pos], "%s=%s,", cmd, arg);
217 return pos;
218}
219
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800220/*
221 * Arguments:
222 * argv[2] - wlan interface
223 * argv[3] - softap interface
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800224 * argv[4] - SSID
225 * argv[5] - Security
226 * argv[6] - Key
227 * argv[7] - Channel
228 * argv[8] - Preamble
229 * argv[9] - Max SCB
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800230 */
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800231int SoftapController::setSoftap(int argc, char *argv[]) {
Kenny Roota2d7e3e2010-03-15 14:26:36 -0700232 unsigned char psk[SHA256_DIGEST_LENGTH];
233 char psk_str[2*SHA256_DIGEST_LENGTH+1];
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800234 struct iwreq wrq;
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800235 int fnum, ret, i = 0;
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800236 char *ssid;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800237
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800238 if (mSock < 0) {
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800239 LOGE("Softap set - failed to open socket");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800240 return -1;
241 }
242 if (argc < 4) {
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800243 LOGE("Softap set - missing arguments");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800244 return -1;
245 }
246
Dmitry Shmidt9178b732010-03-12 13:04:09 -0800247 fnum = getPrivFuncNum(argv[2], "AP_SET_CFG");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800248 if (fnum < 0) {
249 LOGE("Softap set - function not supported");
250 return -1;
251 }
252
253 strncpy(mIface, argv[3], sizeof(mIface));
254 strncpy(wrq.ifr_name, argv[2], sizeof(wrq.ifr_name));
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800255
256 /* Create command line */
257 i = addParam(i, "ASCII_CMD", "AP_CFG");
258 if (argc > 4) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800259 ssid = argv[4];
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800260 } else {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800261 ssid = (char *)"AndroidAP";
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800262 }
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800263 i = addParam(i, "SSID", ssid);
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800264 if (argc > 5) {
265 i = addParam(i, "SEC", argv[5]);
266 } else {
267 i = addParam(i, "SEC", "open");
268 }
269 if (argc > 6) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800270 int j;
Kenny Roota2d7e3e2010-03-15 14:26:36 -0700271 // Use the PKCS#5 PBKDF2 with 4096 iterations
272 PKCS5_PBKDF2_HMAC_SHA1(argv[6], strlen(argv[6]),
273 reinterpret_cast<const unsigned char *>(ssid), strlen(ssid),
274 4096, SHA256_DIGEST_LENGTH, psk);
275 for (j=0; j < SHA256_DIGEST_LENGTH; j++) {
Dmitry Shmidt321f95a2010-03-09 15:46:34 -0800276 sprintf(&psk_str[j<<1], "%02x", psk[j]);
277 }
278 psk_str[j<<1] = '\0';
279 i = addParam(i, "KEY", psk_str);
Dmitry Shmidt7977d672010-03-09 10:57:59 -0800280 } else {
281 i = addParam(i, "KEY", "12345678");
282 }
283 if (argc > 7) {
284 i = addParam(i, "CHANNEL", argv[7]);
285 } else {
286 i = addParam(i, "CHANNEL", "6");
287 }
288 if (argc > 8) {
289 i = addParam(i, "PREAMBLE", argv[8]);
290 } else {
291 i = addParam(i, "PREAMBLE", "0");
292 }
293 if (argc > 9) {
294 i = addParam(i, "MAX_SCB", argv[9]);
295 } else {
296 i = addParam(i, "MAX_SCB", "8");
297 }
298 if ((i < 0) || ((unsigned)(i + 4) >= sizeof(mBuf))) {
299 LOGE("Softap set - command is too big");
300 return i;
301 }
302 sprintf(&mBuf[i], "END");
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800303
304 wrq.u.data.length = strlen(mBuf) + 1;
305 wrq.u.data.pointer = mBuf;
306 wrq.u.data.flags = 0;
307 /* system("iwpriv eth0 WL_AP_CFG ASCII_CMD=AP_CFG,SSID=\"AndroidAP\",SEC=\"open\",KEY=12345,CHANNEL=1,PREAMBLE=0,MAX_SCB=8,END"); */
308 ret = ioctl(mSock, fnum, &wrq);
309 if (ret) {
310 LOGE("Softap set - failed: %d", ret);
311 }
312 else {
313 LOGD("Softap set - Ok");
314 }
315 return ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800316}
Dmitry Shmidt31fd6c52010-03-12 10:01:58 -0800317
318/*
319 * Arguments:
320 * argv[2] - interface name
321 * argv[3] - AP or STA
322 */
323int SoftapController::fwReloadSoftap(int argc, char *argv[])
324{
325 struct iwreq wrq;
326 int fnum, ret, i = 0;
327 char *iface;
328
329 if (mSock < 0) {
330 LOGE("Softap fwrealod - failed to open socket");
331 return -1;
332 }
333 if (argc < 4) {
334 LOGE("Softap fwreload - missing arguments");
335 return -1;
336 }
337
338 iface = argv[2];
339 fnum = getPrivFuncNum(iface, "WL_FW_RELOAD");
340 if (fnum < 0) {
341 LOGE("Softap fwReload - function not supported");
342 return -1;
343 }
344
345 if (strcmp(argv[3], "AP") == 0) {
346#ifdef WIFI_DRIVER_FW_AP_PATH
347 sprintf(mBuf, "FW_PATH=%s", WIFI_DRIVER_FW_AP_PATH);
348#endif
349 } else {
350#ifdef WIFI_DRIVER_FW_STA_PATH
351 sprintf(mBuf, "FW_PATH=%s", WIFI_DRIVER_FW_STA_PATH);
352#endif
353 }
354 strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
355 wrq.u.data.length = strlen(mBuf) + 1;
356 wrq.u.data.pointer = mBuf;
357 wrq.u.data.flags = 0;
358 ret = ioctl(mSock, fnum, &wrq);
359 if (ret) {
360 LOGE("Softap fwReload - failed: %d", ret);
361 }
362 else {
363 LOGD("Softap fwReload - Ok");
364 }
365 return ret;
366}