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