SoftapController.cpp 9.38 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>

#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <netinet/in.h>
#include <arpa/inet.h>

29 30
#include <linux/wireless.h>

31 32 33
#include <openssl/evp.h>
#include <openssl/sha.h>

34 35 36 37 38 39 40
#define LOG_TAG "SoftapController"
#include <cutils/log.h>

#include "SoftapController.h"

SoftapController::SoftapController() {
    mPid = 0;
41 42 43 44
    mSock = socket(AF_INET, SOCK_DGRAM, 0);
    if (mSock < 0)
        LOGE("Failed to open socket");
    memset(mIface, 0, sizeof(mIface));
45 46 47
}

SoftapController::~SoftapController() {
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
    if (mSock >= 0)
        close(mSock);
}

int SoftapController::getPrivFuncNum(char *iface, const char *fname) {
    struct iwreq wrq;
    struct iw_priv_args *priv_ptr;
    int i, ret;

    strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
    wrq.u.data.pointer = mBuf;
    wrq.u.data.length = sizeof(mBuf) / sizeof(struct iw_priv_args);
    wrq.u.data.flags = 0;
    if ((ret = ioctl(mSock, SIOCGIWPRIV, &wrq)) < 0) {
        LOGE("SIOCGIPRIV failed: %d", ret);
        return ret;
    }
    priv_ptr = (struct iw_priv_args *)wrq.u.data.pointer;
    for(i=0;(i < wrq.u.data.length);i++) {
        if (strcmp(priv_ptr[i].name, fname) == 0)
            return priv_ptr[i].cmd;
    }
    return -1;
71 72
}

73 74 75 76 77
int SoftapController::startDriver(char *iface) {
    struct iwreq wrq;
    int fnum, ret;

    if (mSock < 0) {
78
        LOGE("Softap driver start - failed to open socket");
79 80 81
        return -1;
    }
    if (!iface || (iface[0] == '\0')) {
82
        LOGD("Softap driver start - wrong interface");
83 84 85 86
        iface = mIface;
    }
    fnum = getPrivFuncNum(iface, "START");
    if (fnum < 0) {
87
        LOGE("Softap driver start - function not supported");
88 89 90 91 92 93 94
        return -1;
    }
    strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
    wrq.u.data.length = 0;
    wrq.u.data.pointer = mBuf;
    wrq.u.data.flags = 0;
    ret = ioctl(mSock, fnum, &wrq);
95 96
    usleep(AP_DRIVER_START_DELAY);
    LOGD("Softap driver start: %d", ret);
97 98 99 100 101 102 103 104
    return ret;
}

int SoftapController::stopDriver(char *iface) {
    struct iwreq wrq;
    int fnum, ret;

    if (mSock < 0) {
105
        LOGE("Softap driver stop - failed to open socket");
106 107 108
        return -1;
    }
    if (!iface || (iface[0] == '\0')) {
109
        LOGD("Softap driver stop - wrong interface");
110 111 112 113
        iface = mIface;
    }
    fnum = getPrivFuncNum(iface, "STOP");
    if (fnum < 0) {
114
        LOGE("Softap driver stop - function not supported");
115 116 117 118 119 120 121
        return -1;
    }
    strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
    wrq.u.data.length = 0;
    wrq.u.data.pointer = mBuf;
    wrq.u.data.flags = 0;
    ret = ioctl(mSock, fnum, &wrq);
122
    LOGD("Softap driver stop: %d", ret);
123 124 125
    return ret;
}

126
int SoftapController::startSoftap() {
127
    struct iwreq wrq;
128
    pid_t pid = 1;
129
    int fnum, ret = 0;
130 131 132

    if (mPid) {
        LOGE("Softap already started");
133
        return 0;
134
    }
135
    if (mSock < 0) {
136
        LOGE("Softap startap - failed to open socket");
137 138
        return -1;
    }
139 140 141 142 143 144
#if 0
   if ((pid = fork()) < 0) {
        LOGE("fork failed (%s)", strerror(errno));
        return -1;
    }
#endif
145
    /* system("iwpriv wl0.1 AP_BSS_START"); */
146
    if (!pid) {
147 148
        /* start hostapd */
        return ret;
149
    } else {
150 151
        fnum = getPrivFuncNum(mIface, "AP_BSS_START");
        if (fnum < 0) {
152
            LOGE("Softap startap - function not supported");
153 154 155 156 157 158 159 160
            return -1;
        }
        strncpy(wrq.ifr_name, mIface, sizeof(wrq.ifr_name));
        wrq.u.data.length = 0;
        wrq.u.data.pointer = mBuf;
        wrq.u.data.flags = 0;
        ret = ioctl(mSock, fnum, &wrq);
        if (ret) {
161
            LOGE("Softap startap - failed: %d", ret);
162 163 164
        }
        else {
           mPid = pid;
165
           LOGD("Softap startap - Ok");
166
           usleep(AP_BSS_START_DELAY);
167
        }
168
    }
169
    return ret;
170 171 172 173

}

int SoftapController::stopSoftap() {
174 175 176
    struct iwreq wrq;
    int fnum, ret;

177 178 179 180
    if (mPid == 0) {
        LOGE("Softap already stopped");
        return 0;
    }
181
    if (mSock < 0) {
182
        LOGE("Softap stopap - failed to open socket");
183 184
        return -1;
    }
185
    fnum = getPrivFuncNum(mIface, "AP_BSS_STOP");
186
    if (fnum < 0) {
187
        LOGE("Softap stopap - function not supported");
188 189 190 191 192 193 194
        return -1;
    }
    strncpy(wrq.ifr_name, mIface, sizeof(wrq.ifr_name));
    wrq.u.data.length = 0;
    wrq.u.data.pointer = mBuf;
    wrq.u.data.flags = 0;
    ret = ioctl(mSock, fnum, &wrq);
195 196 197 198 199 200
#if 0
    LOGD("Stopping Softap service");
    kill(mPid, SIGTERM);
    waitpid(mPid, NULL, 0);
#endif
    mPid = 0;
201
    LOGD("Softap service stopped: %d", ret);
202
    usleep(AP_BSS_STOP_DELAY);
203
    return ret;
204 205 206 207 208 209
}

bool SoftapController::isSoftapStarted() {
    return (mPid != 0 ? true : false);
}

210 211 212 213 214 215 216 217 218 219 220 221
int SoftapController::addParam(int pos, const char *cmd, const char *arg)
{
    if (pos < 0)
        return pos;
    if ((unsigned)(pos + strlen(cmd) + strlen(arg) + 1) >= sizeof(mBuf)) {
        LOGE("Command line is too big");
        return -1;
    }
    pos += sprintf(&mBuf[pos], "%s=%s,", cmd, arg);
    return pos;
}

222 223 224 225
/*
 * Arguments:
 *      argv[2] - wlan interface
 *      argv[3] - softap interface
226 227 228 229 230 231
 *      argv[4] - SSID
 *	argv[5] - Security
 *	argv[6] - Key
 *	argv[7] - Channel
 *	argv[8] - Preamble
 *	argv[9] - Max SCB
232
 */
233
int SoftapController::setSoftap(int argc, char *argv[]) {
234 235
    unsigned char psk[SHA256_DIGEST_LENGTH];
    char psk_str[2*SHA256_DIGEST_LENGTH+1];
236
    struct iwreq wrq;
237
    int fnum, ret, i = 0;
238
    char *ssid;
239 240

    if (mSock < 0) {
241
        LOGE("Softap set - failed to open socket");
242 243 244
        return -1;
    }
    if (argc < 4) {
245
        LOGE("Softap set - missing arguments");
246 247 248
        return -1;
    }

249
    fnum = getPrivFuncNum(argv[2], "AP_SET_CFG");
250 251 252 253 254 255 256
    if (fnum < 0) {
        LOGE("Softap set - function not supported");
        return -1;
    }

    strncpy(mIface, argv[3], sizeof(mIface));
    strncpy(wrq.ifr_name, argv[2], sizeof(wrq.ifr_name));
257 258 259 260

    /* Create command line */
    i = addParam(i, "ASCII_CMD", "AP_CFG");
    if (argc > 4) {
261
        ssid = argv[4];
262
    } else {
263
        ssid = (char *)"AndroidAP";
264
    }
265
    i = addParam(i, "SSID", ssid);
266 267 268 269 270 271
    if (argc > 5) {
        i = addParam(i, "SEC", argv[5]);
    } else {
        i = addParam(i, "SEC", "open");
    }
    if (argc > 6) {
272
        int j;
273 274 275 276 277
        // Use the PKCS#5 PBKDF2 with 4096 iterations
        PKCS5_PBKDF2_HMAC_SHA1(argv[6], strlen(argv[6]),
                reinterpret_cast<const unsigned char *>(ssid), strlen(ssid),
                4096, SHA256_DIGEST_LENGTH, psk);
        for (j=0; j < SHA256_DIGEST_LENGTH; j++) {
278 279 280 281
            sprintf(&psk_str[j<<1], "%02x", psk[j]);
        }
        psk_str[j<<1] = '\0';
        i = addParam(i, "KEY", psk_str);
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    } else {
        i = addParam(i, "KEY", "12345678");
    }
    if (argc > 7) {
        i = addParam(i, "CHANNEL", argv[7]);
    } else {
        i = addParam(i, "CHANNEL", "6");
    }
    if (argc > 8) {
        i = addParam(i, "PREAMBLE", argv[8]);
    } else {
        i = addParam(i, "PREAMBLE", "0");
    }
    if (argc > 9) {
        i = addParam(i, "MAX_SCB", argv[9]);
    } else {
        i = addParam(i, "MAX_SCB", "8");
    }
    if ((i < 0) || ((unsigned)(i + 4) >= sizeof(mBuf))) {
        LOGE("Softap set - command is too big");
        return i;
303
    }
304
    sprintf(&mBuf[i], "END");
305 306 307 308 309 310 311 312 313 314 315

    wrq.u.data.length = strlen(mBuf) + 1;
    wrq.u.data.pointer = mBuf;
    wrq.u.data.flags = 0;
    /* system("iwpriv eth0 WL_AP_CFG ASCII_CMD=AP_CFG,SSID=\"AndroidAP\",SEC=\"open\",KEY=12345,CHANNEL=1,PREAMBLE=0,MAX_SCB=8,END"); */
    ret = ioctl(mSock, fnum, &wrq);
    if (ret) {
        LOGE("Softap set - failed: %d", ret);
    }
    else {
        LOGD("Softap set - Ok");
316
        usleep(AP_SET_CFG_DELAY);
317 318
    }
    return ret;
319
}
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369

/*
 * Arguments:
 *	argv[2] - interface name
 *	argv[3] - AP or STA
 */
int SoftapController::fwReloadSoftap(int argc, char *argv[])
{
    struct iwreq wrq;
    int fnum, ret, i = 0;
    char *iface;

    if (mSock < 0) {
        LOGE("Softap fwrealod - failed to open socket");
        return -1;
    }
    if (argc < 4) {
        LOGE("Softap fwreload - missing arguments");
        return -1;
    }

    iface = argv[2];
    fnum = getPrivFuncNum(iface, "WL_FW_RELOAD");
    if (fnum < 0) {
        LOGE("Softap fwReload - function not supported");
        return -1;
    }

    if (strcmp(argv[3], "AP") == 0) {
#ifdef WIFI_DRIVER_FW_AP_PATH
        sprintf(mBuf, "FW_PATH=%s", WIFI_DRIVER_FW_AP_PATH);
#endif
    } else {
#ifdef WIFI_DRIVER_FW_STA_PATH
        sprintf(mBuf, "FW_PATH=%s", WIFI_DRIVER_FW_STA_PATH);
#endif
    }
    strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
    wrq.u.data.length = strlen(mBuf) + 1;
    wrq.u.data.pointer = mBuf;
    wrq.u.data.flags = 0;
    ret = ioctl(mSock, fnum, &wrq);
    if (ret) {
        LOGE("Softap fwReload - failed: %d", ret);
    }
    else {
        LOGD("Softap fwReload - Ok");
    }
    return ret;
}