diff options
author | Dmitry Shmidt <dimitrysh@google.com> | 2010-03-03 13:14:30 -0800 |
---|---|---|
committer | Dmitry Shmidt <dimitrysh@google.com> | 2010-03-03 13:14:30 -0800 |
commit | 84c65a62fe7b053fed7f20274ca7379627a87b79 (patch) | |
tree | b94a6103e3a2feb076a97d93814c24e88823cef7 | |
parent | e7b9422f0dc7a18041536c63efe74c7095496258 (diff) | |
download | netd-84c65a62fe7b053fed7f20274ca7379627a87b79.tar.gz |
softap: Add basic functionality directly through WEXT
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r-- | SoftapController.cpp | 130 | ||||
-rw-r--r-- | SoftapController.h | 8 |
2 files changed, 130 insertions, 8 deletions
diff --git a/SoftapController.cpp b/SoftapController.cpp index 88bae5c4..66310b1b 100644 --- a/SoftapController.cpp +++ b/SoftapController.cpp @@ -26,6 +26,8 @@ #include <netinet/in.h> #include <arpa/inet.h> +#include <linux/wireless.h> + #define LOG_TAG "SoftapController" #include <cutils/log.h> @@ -33,13 +35,47 @@ SoftapController::SoftapController() { mPid = 0; + mSock = socket(AF_INET, SOCK_DGRAM, 0); + if (mSock < 0) + LOGE("Failed to open socket"); + memset(mIface, 0, sizeof(mIface)); } SoftapController::~SoftapController() { + 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; +#if 0 + for(i=0;(i < wrq.u.data.length);i++) { + LOGE("%s: [%x] %s\n", __func__, priv_ptr[i].cmd, priv_ptr[i].name); + } +#endif + for(i=0;(i < wrq.u.data.length);i++) { + if (strcmp(priv_ptr[i].name, fname) == 0) + return priv_ptr[i].cmd; + } + return -1; } int SoftapController::startSoftap() { + struct iwreq wrq; pid_t pid = 1; + int fnum, ret = 0; LOGD("Softap start"); if (mPid) { @@ -47,43 +83,123 @@ int SoftapController::startSoftap() { errno = EBUSY; return -1; } + if (mSock < 0) { + LOGE("Failed to open socket"); + return -1; + } #if 0 if ((pid = fork()) < 0) { LOGE("fork failed (%s)", strerror(errno)); return -1; } #endif + /* system("iwpriv wl0.1 AP_BSS_START"); */ if (!pid) { - LOGE("Softap Started"); - return 0; + /* start hostapd */ + return ret; } else { - mPid = pid; + LOGD("Softap Started: %s", mIface); + fnum = getPrivFuncNum(mIface, "AP_BSS_START"); + if (fnum < 0) { + LOGE("Softap start - function not supported"); + 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) { + LOGE("Softap start - failed: %d", ret); + } + else { + mPid = pid; + LOGD("Softap start - Ok"); + } } - return 0; + return ret; } int SoftapController::stopSoftap() { + struct iwreq wrq; + int fnum, ret; + LOGD("Softap stop"); if (mPid == 0) { LOGE("Softap already stopped"); return 0; } + if (mSock < 0) { + LOGE("Failed to open socket"); + return -1; + } + fnum = getPrivFuncNum(mIface, "WL_AP_STOP"); + if (fnum < 0) { + LOGE("Softap stop - function not supported"); + 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 0 LOGD("Stopping Softap service"); kill(mPid, SIGTERM); waitpid(mPid, NULL, 0); #endif mPid = 0; - LOGD("Softap service stopped"); - return 0; + LOGD("Softap service stopped: %d", ret); + return ret; } bool SoftapController::isSoftapStarted() { return (mPid != 0 ? true : false); } +/* + * Arguments: + * argv[2] - wlan interface + * argv[3] - softap interface + * argv[4] - command line + */ int SoftapController::setSoftap(int argc, char *argv[]) { + struct iwreq wrq; + int fnum, ret; + LOGD("Softap set"); - return 0; + if (mSock < 0) { + LOGE("Failed to open socket"); + return -1; + } + if (argc < 4) { + LOGE("Missing arguments"); + return -1; + } + + fnum = getPrivFuncNum(argv[2], "WL_AP_CFG"); + 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)); + if (argc >= 4) { + strncpy(mBuf, argv[4], sizeof(mBuf)); + } + + 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"); + } + return ret; } diff --git a/SoftapController.h b/SoftapController.h index 1af113dc..dc8936ad 100644 --- a/SoftapController.h +++ b/SoftapController.h @@ -18,12 +18,18 @@ #define _SOFTAP_CONTROLLER_H #include <linux/in.h> - +#include <net/if.h> #include <utils/List.h> +#define SOFTAP_MAX_BUFFER_SIZE 4096 + class SoftapController { + char mBuf[SOFTAP_MAX_BUFFER_SIZE]; + char mIface[IFNAMSIZ]; pid_t mPid; + int mSock; + int getPrivFuncNum(char *iface, const char *fname); public: SoftapController(); virtual ~SoftapController(); |