/* * 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 #include #include #include #include #include #include #include #include #include #define LOG_TAG "SoftapController" #include #include "SoftapController.h" 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) { LOGE("Softap already started"); 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) { /* start hostapd */ return ret; } else { 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 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: %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"); 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; }