SoftapController.cpp revision 54cf7fda69c3c442e7d2ac370a9c942fdb38dcd7
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h>
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/socket.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/ioctl.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/wait.h>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/in.h>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <arpa/inet.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <linux/wireless.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <openssl/evp.h>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <openssl/sha.h>
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "SoftapController"
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/log.h>
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netutils/ifc.h>
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "wifi.h"
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SoftapController.h"
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSoftapController::SoftapController() {
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mPid = 0;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mSock = socket(AF_INET, SOCK_DGRAM, 0);
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock < 0)
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Failed to open socket");
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    memset(mIface, 0, sizeof(mIface));
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSoftapController::~SoftapController() {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock >= 0)
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close(mSock);
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::setCommand(char *iface, const char *fname, unsigned buflen) {
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_HOSTAPD
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char tBuf[SOFTAP_MAX_BUFFER_SIZE];
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct iwreq wrq;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct iw_priv_args *priv_ptr;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int i, j, ret;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int cmd = 0, sub_cmd = 0;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    wrq.u.data.pointer = tBuf;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    wrq.u.data.length = sizeof(tBuf) / sizeof(struct iw_priv_args);
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    wrq.u.data.flags = 0;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((ret = ioctl(mSock, SIOCGIWPRIV, &wrq)) < 0) {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("SIOCGIPRIV failed: %d", ret);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ret;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    priv_ptr = (struct iw_priv_args *)wrq.u.data.pointer;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for(i=0; i < wrq.u.data.length;i++) {
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (strcmp(priv_ptr[i].name, fname) == 0) {
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cmd = priv_ptr[i].cmd;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (i == wrq.u.data.length) {
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("iface:%s, fname: %s - function not supported", iface, fname);
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (cmd < SIOCDEVPRIVATE) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for(j=0; j < i; j++) {
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((priv_ptr[j].set_args == priv_ptr[i].set_args) &&
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (priv_ptr[j].get_args == priv_ptr[i].get_args) &&
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (priv_ptr[j].name[0] == '\0'))
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (j == i) {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("iface:%s, fname: %s - invalid private ioctl", iface, fname);
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sub_cmd = cmd;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cmd = priv_ptr[j].cmd;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((buflen == 0) && (*mBuf != 0))
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        wrq.u.data.length = strlen(mBuf) + 1;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        wrq.u.data.length = buflen;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    wrq.u.data.pointer = mBuf;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    wrq.u.data.flags = sub_cmd;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = ioctl(mSock, cmd, &wrq);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::startDriver(char *iface) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock < 0) {
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap driver start - failed to open socket");
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!iface || (iface[0] == '\0')) {
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGD("Softap driver start - wrong interface");
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        iface = mIface;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *mBuf = 0;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = setCommand(iface, "START");
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ret < 0) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap driver start: %d", ret);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ret;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_HOSTAPD
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ifc_init();
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = ifc_up(iface);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ifc_close();
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    usleep(AP_DRIVER_START_DELAY);
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGD("Softap driver start: %d", ret);
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::stopDriver(char *iface) {
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock < 0) {
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap driver stop - failed to open socket");
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!iface || (iface[0] == '\0')) {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGD("Softap driver stop - wrong interface");
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        iface = mIface;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *mBuf = 0;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_HOSTAPD
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ifc_init();
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = ifc_down(iface);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ifc_close();
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ret < 0) {
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap %s down: %d", iface, ret);
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ret;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = setCommand(iface, "STOP");
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGD("Softap driver stop: %d", ret);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::startSoftap() {
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pid_t pid = 1;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret = 0;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mPid) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap already started");
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock < 0) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap startap - failed to open socket");
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_HOSTAPD
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((pid = fork()) < 0) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("fork failed (%s)", strerror(errno));
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!pid) {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_HOSTAPD
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (execl("/system/bin/hostapd", "/system/bin/hostapd", "-B",
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                  "/data/misc/wifi/hostapd.conf", (char *) NULL)) {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           LOGE("execl failed (%s)", strerror(errno));
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Should never get here!");
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *mBuf = 0;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ret = setCommand(mIface, "AP_BSS_START");
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ret) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Softap startap - failed: %d", ret);
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           mPid = pid;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           LOGD("Softap startap - Ok");
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           usleep(AP_BSS_START_DELAY);
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::stopSoftap() {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mPid == 0) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap already stopped");
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_HOSTAPD
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGD("Stopping Softap service");
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    kill(mPid, SIGTERM);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    waitpid(mPid, NULL, 0);
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock < 0) {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap stopap - failed to open socket");
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *mBuf = 0;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = setCommand(mIface, "AP_BSS_STOP");
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mPid = 0;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGD("Softap service stopped: %d", ret);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    usleep(AP_BSS_STOP_DELAY);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool SoftapController::isSoftapStarted() {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (mPid != 0 ? true : false);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::addParam(int pos, const char *cmd, const char *arg)
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pos < 0)
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return pos;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((unsigned)(pos + strlen(cmd) + strlen(arg) + 1) >= sizeof(mBuf)) {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Command line is too big");
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pos += sprintf(&mBuf[pos], "%s=%s,", cmd, arg);
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return pos;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Arguments:
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      argv[2] - wlan interface
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      argv[3] - softap interface
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      argv[4] - SSID
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *	argv[5] - Security
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *	argv[6] - Key
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *	argv[7] - Channel
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *	argv[8] - Preamble
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *	argv[9] - Max SCB
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::setSoftap(int argc, char *argv[]) {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned char psk[SHA256_DIGEST_LENGTH];
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char psk_str[2*SHA256_DIGEST_LENGTH+1];
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret, i = 0;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char *ssid, *iface;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock < 0) {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap set - failed to open socket");
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc < 4) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap set - missing arguments");
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    strncpy(mIface, argv[3], sizeof(mIface));
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    iface = argv[2];
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* Create command line */
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    i = addParam(i, "ASCII_CMD", "AP_CFG");
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc > 4) {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ssid = argv[4];
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ssid = (char *)"AndroidAP";
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    i = addParam(i, "SSID", ssid);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc > 5) {
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "SEC", argv[5]);
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "SEC", "open");
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc > 6) {
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int j;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Use the PKCS#5 PBKDF2 with 4096 iterations
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PKCS5_PBKDF2_HMAC_SHA1(argv[6], strlen(argv[6]),
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                reinterpret_cast<const unsigned char *>(ssid), strlen(ssid),
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                4096, SHA256_DIGEST_LENGTH, psk);
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (j=0; j < SHA256_DIGEST_LENGTH; j++) {
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sprintf(&psk_str[j<<1], "%02x", psk[j]);
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        psk_str[j<<1] = '\0';
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "KEY", psk_str);
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "KEY", "12345678");
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc > 7) {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "CHANNEL", argv[7]);
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "CHANNEL", "6");
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc > 8) {
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "PREAMBLE", argv[8]);
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "PREAMBLE", "0");
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc > 9) {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "MAX_SCB", argv[9]);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        i = addParam(i, "MAX_SCB", "8");
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((i < 0) || ((unsigned)(i + 4) >= sizeof(mBuf))) {
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap set - command is too big");
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return i;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sprintf(&mBuf[i], "END");
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* system("iwpriv eth0 WL_AP_CFG ASCII_CMD=AP_CFG,SSID=\"AndroidAP\",SEC=\"open\",KEY=12345,CHANNEL=1,PREAMBLE=0,MAX_SCB=8,END"); */
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = setCommand(iface, "AP_SET_CFG");
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ret) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap set - failed: %d", ret);
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGD("Softap set - Ok");
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        usleep(AP_SET_CFG_DELAY);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Arguments:
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *	argv[2] - interface name
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *	argv[3] - AP or STA
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::fwReloadSoftap(int argc, char *argv[])
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret, i = 0;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char *iface;
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char *fwpath;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock < 0) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap fwrealod - failed to open socket");
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (argc < 4) {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap fwreload - missing arguments");
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    iface = argv[2];
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (strcmp(argv[3], "AP") == 0) {
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (strcmp(argv[3], "P2P") == 0) {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!fwpath)
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_HOSTAPD
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = wifi_change_fw_path((const char *)fwpath);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sprintf(mBuf, "FW_PATH=%s", fwpath);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = setCommand(iface, "WL_FW_RELOAD");
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ret) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap fwReload - failed: %d", ret);
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGD("Softap fwReload - Ok");
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint SoftapController::clientsSoftap(char **retbuf)
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mSock < 0) {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap clients - failed to open socket");
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *mBuf = 0;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ret = setCommand(mIface, "AP_GET_STA_LIST", SOFTAP_MAX_BUFFER_SIZE);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ret) {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Softap clients - failed: %d", ret);
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        asprintf(retbuf, "Softap clients:%s", mBuf);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGD("Softap clients:%s", mBuf);
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project