зеркало из https://github.com/mozilla/gecko-dev.git
1411 строки
43 KiB
C++
1411 строки
43 KiB
C++
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
|
|
*
|
|
* 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 "NetworkUtils.h"
|
|
|
|
#include <android/log.h>
|
|
#include <cutils/properties.h>
|
|
#include <limits>
|
|
#include "mozilla/dom/network/NetUtils.h"
|
|
|
|
#define _DEBUG 0
|
|
|
|
#define WARN(args...) __android_log_print(ANDROID_LOG_WARN, "NetworlUtils", ## args)
|
|
#define ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "NetworkUtils", ## args)
|
|
|
|
#if _DEBUG
|
|
#define DEBUG(args...) __android_log_print(ANDROID_LOG_DEBUG, "NetworkUtils" , ## args)
|
|
#else
|
|
#define DEBUG(args...)
|
|
#endif
|
|
|
|
using namespace mozilla::dom;
|
|
using namespace mozilla::ipc;
|
|
|
|
static const char* PERSIST_SYS_USB_CONFIG_PROPERTY = "persist.sys.usb.config";
|
|
static const char* SYS_USB_CONFIG_PROPERTY = "sys.usb.config";
|
|
static const char* SYS_USB_STATE_PROPERTY = "sys.usb.state";
|
|
|
|
static const char* USB_FUNCTION_RNDIS = "rndis";
|
|
static const char* USB_FUNCTION_ADB = "adb";
|
|
|
|
// Use this command to continue the function chain.
|
|
static const char* DUMMY_COMMAND = "tether status";
|
|
|
|
// Retry 20 times (2 seconds) for usb state transition.
|
|
static const uint32_t USB_FUNCTION_RETRY_TIMES = 20;
|
|
// Check "sys.usb.state" every 100ms.
|
|
static const uint32_t USB_FUNCTION_RETRY_INTERVAL = 100;
|
|
|
|
// 1xx - Requested action is proceeding
|
|
static const uint32_t NETD_COMMAND_PROCEEDING = 100;
|
|
// 2xx - Requested action has been successfully completed
|
|
static const uint32_t NETD_COMMAND_OKAY = 200;
|
|
// 4xx - The command is accepted but the requested action didn't
|
|
// take place.
|
|
static const uint32_t NETD_COMMAND_FAIL = 400;
|
|
// 5xx - The command syntax or parameters error
|
|
static const uint32_t NETD_COMMAND_ERROR = 500;
|
|
// 6xx - Unsolicited broadcasts
|
|
static const uint32_t NETD_COMMAND_UNSOLICITED = 600;
|
|
|
|
// Broadcast messages
|
|
static const uint32_t NETD_COMMAND_INTERFACE_CHANGE = 600;
|
|
static const uint32_t NETD_COMMAND_BANDWIDTH_CONTROLLER = 601;
|
|
|
|
static const char* INTERFACE_DELIMIT = "\0";
|
|
static const char* USB_CONFIG_DELIMIT = ",";
|
|
static const char* NETD_MESSAGE_DELIMIT = " ";
|
|
|
|
static const uint32_t BUF_SIZE = 1024;
|
|
|
|
static uint32_t SDK_VERSION;
|
|
|
|
struct IFProperties {
|
|
char gateway[PROPERTY_VALUE_MAX];
|
|
char dns1[PROPERTY_VALUE_MAX];
|
|
char dns2[PROPERTY_VALUE_MAX];
|
|
};
|
|
|
|
struct CurrentCommand {
|
|
CommandChain* chain;
|
|
CommandCallback callback;
|
|
char command[MAX_COMMAND_SIZE];
|
|
};
|
|
|
|
typedef Tuple3<NetdCommand*, CommandChain*, CommandCallback> QueueData;
|
|
|
|
#define GET_CURRENT_NETD_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a)
|
|
#define GET_CURRENT_CHAIN (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].b)
|
|
#define GET_CURRENT_CALLBACK (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].c)
|
|
#define GET_CURRENT_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a->mData)
|
|
|
|
static NetworkUtils* gNetworkUtils;
|
|
static nsTArray<QueueData> gCommandQueue;
|
|
static CurrentCommand gCurrentCommand;
|
|
static bool gPending = false;
|
|
static nsTArray<nsCString> gReason;
|
|
|
|
CommandFunc NetworkUtils::sWifiEnableChain[] = {
|
|
NetworkUtils::wifiFirmwareReload,
|
|
NetworkUtils::startAccessPointDriver,
|
|
NetworkUtils::setAccessPoint,
|
|
NetworkUtils::startSoftAP,
|
|
NetworkUtils::setInterfaceUp,
|
|
NetworkUtils::tetherInterface,
|
|
NetworkUtils::setIpForwardingEnabled,
|
|
NetworkUtils::tetheringStatus,
|
|
NetworkUtils::startTethering,
|
|
NetworkUtils::setDnsForwarders,
|
|
NetworkUtils::enableNat,
|
|
NetworkUtils::wifiTetheringSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sWifiDisableChain[] = {
|
|
NetworkUtils::stopSoftAP,
|
|
NetworkUtils::stopAccessPointDriver,
|
|
NetworkUtils::wifiFirmwareReload,
|
|
NetworkUtils::untetherInterface,
|
|
NetworkUtils::preTetherInterfaceList,
|
|
NetworkUtils::postTetherInterfaceList,
|
|
NetworkUtils::disableNat,
|
|
NetworkUtils::setIpForwardingEnabled,
|
|
NetworkUtils::stopTethering,
|
|
NetworkUtils::wifiTetheringSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sWifiFailChain[] = {
|
|
NetworkUtils::stopSoftAP,
|
|
NetworkUtils::setIpForwardingEnabled,
|
|
NetworkUtils::stopTethering
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sWifiOperationModeChain[] = {
|
|
NetworkUtils::wifiFirmwareReload,
|
|
NetworkUtils::wifiOperationModeSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sUSBEnableChain[] = {
|
|
NetworkUtils::setInterfaceUp,
|
|
NetworkUtils::enableNat,
|
|
NetworkUtils::setIpForwardingEnabled,
|
|
NetworkUtils::tetherInterface,
|
|
NetworkUtils::tetheringStatus,
|
|
NetworkUtils::startTethering,
|
|
NetworkUtils::setDnsForwarders,
|
|
NetworkUtils::usbTetheringSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sUSBDisableChain[] = {
|
|
NetworkUtils::untetherInterface,
|
|
NetworkUtils::preTetherInterfaceList,
|
|
NetworkUtils::postTetherInterfaceList,
|
|
NetworkUtils::disableNat,
|
|
NetworkUtils::setIpForwardingEnabled,
|
|
NetworkUtils::stopTethering,
|
|
NetworkUtils::usbTetheringSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sUSBFailChain[] = {
|
|
NetworkUtils::stopSoftAP,
|
|
NetworkUtils::setIpForwardingEnabled,
|
|
NetworkUtils::stopTethering
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sUpdateUpStreamChain[] = {
|
|
NetworkUtils::cleanUpStream,
|
|
NetworkUtils::createUpStream,
|
|
NetworkUtils::updateUpStreamSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sStartDhcpServerChain[] = {
|
|
NetworkUtils::setInterfaceUp,
|
|
NetworkUtils::startTethering,
|
|
NetworkUtils::setDhcpServerSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sStopDhcpServerChain[] = {
|
|
NetworkUtils::stopTethering,
|
|
NetworkUtils::setDhcpServerSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sNetworkInterfaceStatsChain[] = {
|
|
NetworkUtils::getRxBytes,
|
|
NetworkUtils::getTxBytes,
|
|
NetworkUtils::networkInterfaceStatsSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sNetworkInterfaceEnableAlarmChain[] = {
|
|
NetworkUtils::enableAlarm,
|
|
NetworkUtils::setQuota,
|
|
NetworkUtils::setAlarm,
|
|
NetworkUtils::networkInterfaceAlarmSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sNetworkInterfaceDisableAlarmChain[] = {
|
|
NetworkUtils::removeQuota,
|
|
NetworkUtils::disableAlarm,
|
|
NetworkUtils::networkInterfaceAlarmSuccess
|
|
};
|
|
|
|
CommandFunc NetworkUtils::sNetworkInterfaceSetAlarmChain[] = {
|
|
NetworkUtils::setAlarm,
|
|
NetworkUtils::networkInterfaceAlarmSuccess
|
|
};
|
|
|
|
/**
|
|
* Helper function to get the bit length from given mask.
|
|
*/
|
|
static uint32_t getMaskLength(const uint32_t mask)
|
|
{
|
|
uint32_t netmask = ntohl(mask);
|
|
uint32_t len = 0;
|
|
while (netmask & 0x80000000) {
|
|
len++;
|
|
netmask = netmask << 1;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
/**
|
|
* Helper function to split string by seperator, store split result as an nsTArray.
|
|
*/
|
|
static void split(char* str, const char* sep, nsTArray<nsCString>& result)
|
|
{
|
|
char *s = strtok(str, sep);
|
|
while (s != nullptr) {
|
|
result.AppendElement(s);
|
|
s = strtok(nullptr, sep);
|
|
}
|
|
}
|
|
|
|
static void split(char* str, const char* sep, nsTArray<nsString>& result)
|
|
{
|
|
char *s = strtok(str, sep);
|
|
while (s != nullptr) {
|
|
result.AppendElement(NS_ConvertUTF8toUTF16(s));
|
|
s = strtok(nullptr, sep);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function that implement join function.
|
|
*/
|
|
static void join(nsTArray<nsCString>& array, const char* sep, const uint32_t maxlen, char* result)
|
|
{
|
|
#define CHECK_LENGTH(len, add, max) len += add; \
|
|
if (len > max - 1) \
|
|
return; \
|
|
|
|
uint32_t len = 0;
|
|
uint32_t seplen = strlen(sep);
|
|
|
|
if (array.Length() > 0) {
|
|
CHECK_LENGTH(len, strlen(array[0].get()), maxlen)
|
|
strcpy(result, array[0].get());
|
|
|
|
for (uint32_t i = 1; i < array.Length(); i++) {
|
|
CHECK_LENGTH(len, seplen, maxlen)
|
|
strcat(result, sep);
|
|
|
|
CHECK_LENGTH(len, strlen(array[i].get()), maxlen)
|
|
strcat(result, array[i].get());
|
|
}
|
|
}
|
|
|
|
#undef CHECK_LEN
|
|
}
|
|
|
|
/**
|
|
* Helper function to get network interface properties from the system property table.
|
|
*/
|
|
static void getIFProperties(const char* ifname, IFProperties& prop)
|
|
{
|
|
char key[PROPERTY_KEY_MAX];
|
|
snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.gw", ifname);
|
|
property_get(key, prop.gateway, "");
|
|
snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.dns1", ifname);
|
|
property_get(key, prop.dns1, "");
|
|
snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.dns2", ifname);
|
|
property_get(key, prop.dns2, "");
|
|
}
|
|
|
|
static void postMessage(NetworkResultOptions& aResult)
|
|
{
|
|
MOZ_ASSERT(gNetworkUtils);
|
|
MOZ_ASSERT(gNetworkUtils->getMessageCallback());
|
|
|
|
if (*(gNetworkUtils->getMessageCallback()))
|
|
(*(gNetworkUtils->getMessageCallback()))(aResult);
|
|
}
|
|
|
|
static void postMessage(NetworkParams& aOptions, NetworkResultOptions& aResult)
|
|
{
|
|
MOZ_ASSERT(gNetworkUtils);
|
|
MOZ_ASSERT(gNetworkUtils->getMessageCallback());
|
|
|
|
aResult.mId = aOptions.mId;
|
|
|
|
if (*(gNetworkUtils->getMessageCallback()))
|
|
(*(gNetworkUtils->getMessageCallback()))(aResult);
|
|
}
|
|
|
|
void NetworkUtils::next(CommandChain* aChain, bool aError, NetworkResultOptions& aResult)
|
|
{
|
|
if (aError) {
|
|
ErrorCallback onError = aChain->getErrorCallback();
|
|
if(onError) {
|
|
aResult.mError = true;
|
|
(*onError)(aChain->getParams(), aResult);
|
|
}
|
|
delete aChain;
|
|
return;
|
|
}
|
|
CommandFunc f = aChain->getNextCommand();
|
|
if (!f) {
|
|
delete aChain;
|
|
return;
|
|
}
|
|
|
|
(*f)(aChain, next, aResult);
|
|
}
|
|
|
|
/**
|
|
* Send command to netd.
|
|
*/
|
|
void NetworkUtils::nextNetdCommand()
|
|
{
|
|
if (gCommandQueue.IsEmpty() || gPending) {
|
|
return;
|
|
}
|
|
|
|
gCurrentCommand.chain = GET_CURRENT_CHAIN;
|
|
gCurrentCommand.callback = GET_CURRENT_CALLBACK;
|
|
snprintf(gCurrentCommand.command, MAX_COMMAND_SIZE - 1, "%s", GET_CURRENT_COMMAND);
|
|
|
|
DEBUG("Sending \'%s\' command to netd.", gCurrentCommand.command);
|
|
SendNetdCommand(GET_CURRENT_NETD_COMMAND);
|
|
|
|
gCommandQueue.RemoveElementAt(0);
|
|
gPending = true;
|
|
}
|
|
|
|
/**
|
|
* Composite NetdCommand sent to netd
|
|
*
|
|
* @param aCommand Command sent to netd to execute.
|
|
* @param aChain Store command chain data, ex. command parameter.
|
|
* @param aCallback Callback function to be executed when the result of
|
|
* this command is returned from netd.
|
|
*/
|
|
void NetworkUtils::doCommand(const char* aCommand, CommandChain* aChain, CommandCallback aCallback)
|
|
{
|
|
DEBUG("Preparing to send \'%s\' command...", aCommand);
|
|
|
|
NetdCommand* netdCommand = new NetdCommand();
|
|
|
|
// Android JB version adds sequence number to netd command.
|
|
if (SDK_VERSION >= 16) {
|
|
snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "0 %s", aCommand);
|
|
} else {
|
|
snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "%s", aCommand);
|
|
}
|
|
netdCommand->mSize = strlen((char*)netdCommand->mData) + 1;
|
|
|
|
gCommandQueue.AppendElement(QueueData(netdCommand, aChain, aCallback));
|
|
|
|
nextNetdCommand();
|
|
}
|
|
|
|
/*
|
|
* Netd command function
|
|
*/
|
|
#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aChain->getParams().prop).get()
|
|
#define GET_FIELD(prop) aChain->getParams().prop
|
|
|
|
void NetworkUtils::wifiFirmwareReload(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "softap fwreload %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::startAccessPointDriver(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
// Skip the command for sdk version >= 16.
|
|
if (SDK_VERSION >= 16) {
|
|
aResult.mResultCode = 0;
|
|
aResult.mResultReason = NS_ConvertUTF8toUTF16("");
|
|
aCallback(aChain, false, aResult);
|
|
return;
|
|
}
|
|
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "softap start %s", GET_CHAR(mIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::stopAccessPointDriver(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
// Skip the command for sdk version >= 16.
|
|
if (SDK_VERSION >= 16) {
|
|
aResult.mResultCode = 0;
|
|
aResult.mResultReason = NS_ConvertUTF8toUTF16("");
|
|
aCallback(aChain, false, aResult);
|
|
return;
|
|
}
|
|
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "softap stop %s", GET_CHAR(mIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
/**
|
|
* Command format for sdk version < 16
|
|
* Arguments:
|
|
* argv[2] - wlan interface
|
|
* argv[3] - SSID
|
|
* argv[4] - Security
|
|
* argv[5] - Key
|
|
* argv[6] - Channel
|
|
* argv[7] - Preamble
|
|
* argv[8] - Max SCB
|
|
*
|
|
* Command format for sdk version >= 16
|
|
* Arguments:
|
|
* argv[2] - wlan interface
|
|
* argv[3] - SSID
|
|
* argv[4] - Security
|
|
* argv[5] - Key
|
|
*/
|
|
void NetworkUtils::setAccessPoint(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
if (SDK_VERSION >= 16) {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" %s \"%s\"",
|
|
GET_CHAR(mIfname),
|
|
GET_CHAR(mSsid),
|
|
GET_CHAR(mSecurity),
|
|
GET_CHAR(mKey));
|
|
} else {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s %s \"%s\" %s \"%s\" 6 0 8",
|
|
GET_CHAR(mIfname),
|
|
GET_CHAR(mWifictrlinterfacename),
|
|
GET_CHAR(mSsid),
|
|
GET_CHAR(mSecurity),
|
|
GET_CHAR(mKey));
|
|
}
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::cleanUpStream(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0", GET_CHAR(mPreInternalIfname), GET_CHAR(mPreExternalIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::createUpStream(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0", GET_CHAR(mCurInternalIfname), GET_CHAR(mCurExternalIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::startSoftAP(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
const char* command= "softap startap";
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::stopSoftAP(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
const char* command= "softap stopap";
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::getRxBytes(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "interface readrxcounter %s", GET_CHAR(mIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::getTxBytes(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
NetworkParams& options = aChain->getParams();
|
|
options.mRxBytes = atof(NS_ConvertUTF16toUTF8(aResult.mResultReason).get());
|
|
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "interface readtxcounter %s", GET_CHAR(mIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::enableAlarm(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
const char* command= "bandwidth enable";
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::disableAlarm(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
const char* command= "bandwidth disable";
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::setQuota(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setiquota %s %lld", GET_CHAR(mIfname), LLONG_MAX);
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::removeQuota(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeiquota %s", GET_CHAR(mIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::setAlarm(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setinterfacealert %s %ld", GET_CHAR(mIfname), GET_FIELD(mThreshold));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::setInterfaceUp(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
if (SDK_VERSION >= 16) {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s %s",
|
|
GET_CHAR(mIfname),
|
|
GET_CHAR(mIp),
|
|
GET_CHAR(mPrefix),
|
|
GET_CHAR(mLink));
|
|
} else {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s [%s]",
|
|
GET_CHAR(mIfname),
|
|
GET_CHAR(mIp),
|
|
GET_CHAR(mPrefix),
|
|
GET_CHAR(mLink));
|
|
}
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::tetherInterface(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface add %s", GET_CHAR(mIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::preTetherInterfaceList(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
if (SDK_VERSION >= 16) {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list");
|
|
} else {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list 0");
|
|
}
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::postTetherInterfaceList(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
// Send the dummy command to continue the function chain.
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
|
|
|
|
char buf[BUF_SIZE];
|
|
const char* reason = NS_ConvertUTF16toUTF8(aResult.mResultReason).get();
|
|
memcpy(buf, reason, strlen(reason));
|
|
split(buf, INTERFACE_DELIMIT, GET_FIELD(mInterfaceList));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::setIpForwardingEnabled(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
|
|
if (GET_FIELD(mEnable)) {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd enable");
|
|
} else {
|
|
// Don't disable ip forwarding because others interface still need it.
|
|
// Send the dummy command to continue the function chain.
|
|
if (GET_FIELD(mInterfaceList).Length() > 1) {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
|
|
} else {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd disable");
|
|
}
|
|
}
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::tetheringStatus(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
const char* command= "tether status";
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::stopTethering(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
|
|
// Don't stop tethering because others interface still need it.
|
|
// Send the dummy to continue the function chain.
|
|
if (GET_FIELD(mInterfaceList).Length() > 1) {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
|
|
} else {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "tether stop");
|
|
}
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::startTethering(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
|
|
// We don't need to start tethering again.
|
|
// Send the dummy command to continue the function chain.
|
|
if (aResult.mResultReason.Find("started") != kNotFound) {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
|
|
} else {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s", GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp));
|
|
|
|
// If usbStartIp/usbEndIp is not valid, don't append them since
|
|
// the trailing white spaces will be parsed to extra empty args
|
|
// See: http://androidxref.com/4.3_r2.1/xref/system/core/libsysutils/src/FrameworkListener.cpp#78
|
|
if (!GET_FIELD(mUsbStartIp).IsEmpty() && !GET_FIELD(mUsbEndIp).IsEmpty()) {
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "%s %s %s", command, GET_CHAR(mUsbStartIp), GET_CHAR(mUsbEndIp));
|
|
}
|
|
}
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::untetherInterface(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface remove %s", GET_CHAR(mIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::setDnsForwarders(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "tether dns set %s %s", GET_CHAR(mDns1), GET_CHAR(mDns2));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::enableNat(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0", GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
void NetworkUtils::disableNat(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
char command[MAX_COMMAND_SIZE];
|
|
snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0", GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
|
|
|
|
doCommand(command, aChain, aCallback);
|
|
}
|
|
|
|
#undef GET_CHAR
|
|
#undef GET_FIELD
|
|
|
|
/*
|
|
* Netd command success/fail function
|
|
*/
|
|
#define ASSIGN_FIELD(prop) aResult.prop = aChain->getParams().prop;
|
|
#define ASSIGN_FIELD_VALUE(prop, value) aResult.prop = value;
|
|
|
|
#define RUN_CHAIN(param, cmds, err) \
|
|
uint32_t size = sizeof(cmds) / sizeof(CommandFunc); \
|
|
CommandChain* chain = new CommandChain(param, cmds, size, err); \
|
|
NetworkResultOptions result; \
|
|
next(chain, false, result);
|
|
|
|
void NetworkUtils::wifiTetheringFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
|
|
{
|
|
// Notify the main thread.
|
|
postMessage(aOptions, aResult);
|
|
|
|
// If one of the stages fails, we try roll back to ensure
|
|
// we don't leave the network systems in limbo.
|
|
ASSIGN_FIELD_VALUE(mEnable, false)
|
|
RUN_CHAIN(aOptions, sWifiFailChain, nullptr)
|
|
}
|
|
|
|
void NetworkUtils::wifiTetheringSuccess(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
ASSIGN_FIELD(mEnable)
|
|
postMessage(aChain->getParams(), aResult);
|
|
}
|
|
|
|
void NetworkUtils::usbTetheringFail(NetworkParams& aOptions,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
// Notify the main thread.
|
|
postMessage(aOptions, aResult);
|
|
// Try to roll back to ensure
|
|
// we don't leave the network systems in limbo.
|
|
// This parameter is used to disable ipforwarding.
|
|
{
|
|
aOptions.mEnable = false;
|
|
RUN_CHAIN(aOptions, sUSBFailChain, nullptr)
|
|
}
|
|
|
|
// Disable usb rndis function.
|
|
{
|
|
NetworkParams options;
|
|
options.mEnable = false;
|
|
options.mReport = false;
|
|
gNetworkUtils->enableUsbRndis(options);
|
|
}
|
|
}
|
|
|
|
void NetworkUtils::usbTetheringSuccess(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
ASSIGN_FIELD(mEnable)
|
|
postMessage(aChain->getParams(), aResult);
|
|
}
|
|
|
|
void NetworkUtils::networkInterfaceStatsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
|
|
{
|
|
postMessage(aOptions, aResult);
|
|
}
|
|
|
|
void NetworkUtils::networkInterfaceStatsSuccess(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
ASSIGN_FIELD(mRxBytes)
|
|
ASSIGN_FIELD_VALUE(mTxBytes, atof(NS_ConvertUTF16toUTF8(aResult.mResultReason).get()))
|
|
postMessage(aChain->getParams(), aResult);
|
|
}
|
|
|
|
void NetworkUtils::networkInterfaceAlarmFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
|
|
{
|
|
postMessage(aOptions, aResult);
|
|
}
|
|
|
|
void NetworkUtils::networkInterfaceAlarmSuccess(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
// TODO : error is not used , and it is conflict with boolean type error.
|
|
// params.error = parseFloat(params.resultReason);
|
|
postMessage(aChain->getParams(), aResult);
|
|
}
|
|
|
|
void NetworkUtils::updateUpStreamFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
|
|
{
|
|
postMessage(aOptions, aResult);
|
|
}
|
|
|
|
void NetworkUtils::updateUpStreamSuccess(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
ASSIGN_FIELD(mCurExternalIfname)
|
|
ASSIGN_FIELD(mCurInternalIfname)
|
|
postMessage(aChain->getParams(), aResult);
|
|
}
|
|
|
|
void NetworkUtils::setDhcpServerFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
|
|
{
|
|
aResult.mSuccess = false;
|
|
postMessage(aOptions, aResult);
|
|
}
|
|
|
|
void NetworkUtils::setDhcpServerSuccess(CommandChain* aChain, CommandCallback aCallback, NetworkResultOptions& aResult)
|
|
{
|
|
aResult.mSuccess = true;
|
|
postMessage(aChain->getParams(), aResult);
|
|
}
|
|
|
|
void NetworkUtils::wifiOperationModeFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
|
|
{
|
|
postMessage(aOptions, aResult);
|
|
}
|
|
|
|
void NetworkUtils::wifiOperationModeSuccess(CommandChain* aChain,
|
|
CommandCallback aCallback,
|
|
NetworkResultOptions& aResult)
|
|
{
|
|
postMessage(aChain->getParams(), aResult);
|
|
}
|
|
|
|
#undef ASSIGN_FIELD
|
|
#undef ASSIGN_FIELD_VALUE
|
|
|
|
NetworkUtils::NetworkUtils(MessageCallback aCallback)
|
|
: mMessageCallback(aCallback)
|
|
{
|
|
mNetUtils = new NetUtils();
|
|
|
|
char value[PROPERTY_VALUE_MAX];
|
|
property_get("ro.build.version.sdk", value, nullptr);
|
|
SDK_VERSION = atoi(value);
|
|
|
|
gNetworkUtils = this;
|
|
}
|
|
|
|
NetworkUtils::~NetworkUtils()
|
|
{
|
|
}
|
|
|
|
#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aOptions.prop).get()
|
|
|
|
void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
|
|
{
|
|
bool ret = true;
|
|
|
|
if (aOptions.mCmd.EqualsLiteral("removeNetworkRoute")) {
|
|
removeNetworkRoute(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("setDNS")) {
|
|
setDNS(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("setDefaultRouteAndDNS")) {
|
|
setDefaultRouteAndDNS(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("removeDefaultRoute")) {
|
|
removeDefaultRoute(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("addHostRoute")) {
|
|
addHostRoute(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("removeHostRoute")) {
|
|
removeHostRoute(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("removeHostRoutes")) {
|
|
removeHostRoutes(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("getNetworkInterfaceStats")) {
|
|
getNetworkInterfaceStats(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("setNetworkInterfaceAlarm")) {
|
|
setNetworkInterfaceAlarm(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("enableNetworkInterfaceAlarm")) {
|
|
enableNetworkInterfaceAlarm(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("disableNetworkInterfaceAlarm")) {
|
|
disableNetworkInterfaceAlarm(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("setWifiOperationMode")) {
|
|
setWifiOperationMode(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("setDhcpServer")) {
|
|
setDhcpServer(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("setWifiTethering")) {
|
|
setWifiTethering(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("setUSBTethering")) {
|
|
setUSBTethering(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("enableUsbRndis")) {
|
|
enableUsbRndis(aOptions);
|
|
} else if (aOptions.mCmd.EqualsLiteral("updateUpStream")) {
|
|
updateUpStream(aOptions);
|
|
} else {
|
|
WARN("unknon message");
|
|
return;
|
|
}
|
|
|
|
if (!aOptions.mIsAsync) {
|
|
NetworkResultOptions result;
|
|
result.mRet = ret;
|
|
postMessage(aOptions, result);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle received data from netd.
|
|
*/
|
|
void NetworkUtils::onNetdMessage(NetdCommand* aCommand)
|
|
{
|
|
char* data = (char*)aCommand->mData;
|
|
|
|
// get code & reason.
|
|
char* result = strtok(data, NETD_MESSAGE_DELIMIT);
|
|
|
|
if (!result) {
|
|
nextNetdCommand();
|
|
return;
|
|
}
|
|
uint32_t code = atoi(result);
|
|
|
|
if (!isBroadcastMessage(code) && SDK_VERSION >= 16) {
|
|
strtok(nullptr, NETD_MESSAGE_DELIMIT);
|
|
}
|
|
|
|
char* reason = strtok(nullptr, "\0");
|
|
|
|
if (isBroadcastMessage(code)) {
|
|
DEBUG("Receiving broadcast message from netd.");
|
|
DEBUG(" ==> Code: %d Reason: %s", code, reason);
|
|
sendBroadcastMessage(code, reason);
|
|
nextNetdCommand();
|
|
return;
|
|
}
|
|
|
|
// Set pending to false before we handle next command.
|
|
DEBUG("Receiving \"%s\" command response from netd.", gCurrentCommand.command);
|
|
DEBUG(" ==> Code: %d Reason: %s", code, reason);
|
|
|
|
gReason.AppendElement(nsCString(reason));
|
|
|
|
// 1xx response code regards as command is proceeding, we need to wait for
|
|
// final response code such as 2xx, 4xx and 5xx before sending next command.
|
|
if (isProceeding(code)) {
|
|
return;
|
|
}
|
|
|
|
if (isComplete(code)) {
|
|
gPending = false;
|
|
}
|
|
|
|
if (gCurrentCommand.callback) {
|
|
char buf[BUF_SIZE];
|
|
join(gReason, INTERFACE_DELIMIT, BUF_SIZE, buf);
|
|
|
|
NetworkResultOptions result;
|
|
result.mResultCode = code;
|
|
result.mResultReason = NS_ConvertUTF8toUTF16(buf);
|
|
join(gReason, INTERFACE_DELIMIT, BUF_SIZE, buf);
|
|
(*gCurrentCommand.callback)(gCurrentCommand.chain, isError(code), result);
|
|
gReason.Clear();
|
|
}
|
|
|
|
// Handling pending commands if any.
|
|
if (isComplete(code)) {
|
|
nextNetdCommand();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Start/Stop DHCP server.
|
|
*/
|
|
bool NetworkUtils::setDhcpServer(NetworkParams& aOptions)
|
|
{
|
|
if (aOptions.mEnabled) {
|
|
aOptions.mWifiStartIp = aOptions.mStartIp;
|
|
aOptions.mWifiEndIp = aOptions.mEndIp;
|
|
aOptions.mIp = aOptions.mServerIp;
|
|
aOptions.mPrefix = aOptions.mMaskLength;
|
|
aOptions.mLink = NS_ConvertUTF8toUTF16("up");
|
|
|
|
RUN_CHAIN(aOptions, sStartDhcpServerChain, setDhcpServerFail)
|
|
} else {
|
|
RUN_CHAIN(aOptions, sStopDhcpServerChain, setDhcpServerFail)
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Set DNS servers for given network interface.
|
|
*/
|
|
bool NetworkUtils::setDNS(NetworkParams& aOptions)
|
|
{
|
|
IFProperties interfaceProperties;
|
|
getIFProperties(GET_CHAR(mIfname), interfaceProperties);
|
|
|
|
if (aOptions.mDns1_str.IsEmpty()) {
|
|
property_set("net.dns1", interfaceProperties.dns1);
|
|
} else {
|
|
property_set("net.dns1", GET_CHAR(mDns1_str));
|
|
}
|
|
|
|
if (aOptions.mDns2_str.IsEmpty()) {
|
|
property_set("net.dns2", interfaceProperties.dns2);
|
|
} else {
|
|
property_set("net.dns2", GET_CHAR(mDns2_str));
|
|
}
|
|
|
|
// Bump the DNS change property.
|
|
char dnschange[PROPERTY_VALUE_MAX];
|
|
property_get("net.dnschange", dnschange, "0");
|
|
|
|
char num[PROPERTY_VALUE_MAX];
|
|
snprintf(num, PROPERTY_VALUE_MAX - 1, "%d", atoi(dnschange) + 1);
|
|
property_set("net.dnschange", num);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Set default route and DNS servers for given network interface.
|
|
*/
|
|
bool NetworkUtils::setDefaultRouteAndDNS(NetworkParams& aOptions)
|
|
{
|
|
if (!aOptions.mOldIfname.IsEmpty()) {
|
|
mNetUtils->do_ifc_remove_default_route(GET_CHAR(mOldIfname));
|
|
}
|
|
|
|
IFProperties ifprops;
|
|
getIFProperties(GET_CHAR(mIfname), ifprops);
|
|
|
|
if (aOptions.mGateway_str.IsEmpty()) {
|
|
mNetUtils->do_ifc_set_default_route(GET_CHAR(mIfname), inet_addr(ifprops.gateway));
|
|
} else {
|
|
mNetUtils->do_ifc_set_default_route(GET_CHAR(mIfname), inet_addr(GET_CHAR(mGateway_str)));
|
|
}
|
|
|
|
setDNS(aOptions);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Remove default route for given network interface.
|
|
*/
|
|
bool NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
|
|
{
|
|
mNetUtils->do_ifc_remove_default_route(GET_CHAR(mIfname));
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Add host route for given network interface.
|
|
*/
|
|
bool NetworkUtils::addHostRoute(NetworkParams& aOptions)
|
|
{
|
|
uint32_t length = aOptions.mHostnames.Length();
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
mNetUtils->do_ifc_add_route(GET_CHAR(mIfname), GET_CHAR(mHostnames[i]), 32, GET_CHAR(mGateway));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Remove host route for given network interface.
|
|
*/
|
|
bool NetworkUtils::removeHostRoute(NetworkParams& aOptions)
|
|
{
|
|
uint32_t length = aOptions.mHostnames.Length();
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
mNetUtils->do_ifc_remove_route(GET_CHAR(mIfname), GET_CHAR(mHostnames[i]), 32, GET_CHAR(mGateway));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Remove the routes associated with the named interface.
|
|
*/
|
|
bool NetworkUtils::removeHostRoutes(NetworkParams& aOptions)
|
|
{
|
|
mNetUtils->do_ifc_remove_host_routes(GET_CHAR(mIfname));
|
|
return true;
|
|
}
|
|
|
|
bool NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
|
|
{
|
|
uint32_t ip = inet_addr(GET_CHAR(mIp));
|
|
uint32_t netmask = inet_addr(GET_CHAR(mNetmask));
|
|
uint32_t subnet = ip & netmask;
|
|
uint32_t prefixLength = getMaskLength(netmask);
|
|
const char* gateway = "0.0.0.0";
|
|
struct in_addr addr;
|
|
addr.s_addr = subnet;
|
|
const char* dst = inet_ntoa(addr);
|
|
|
|
mNetUtils->do_ifc_remove_default_route(GET_CHAR(mIfname));
|
|
mNetUtils->do_ifc_remove_route(GET_CHAR(mIfname), dst, prefixLength, gateway);
|
|
return true;
|
|
}
|
|
|
|
bool NetworkUtils::getNetworkInterfaceStats(NetworkParams& aOptions)
|
|
{
|
|
DEBUG("getNetworkInterfaceStats: %s", GET_CHAR(mIfname));
|
|
aOptions.mRxBytes = -1;
|
|
aOptions.mTxBytes = -1;
|
|
|
|
RUN_CHAIN(aOptions, sNetworkInterfaceStatsChain, networkInterfaceStatsFail);
|
|
return true;
|
|
}
|
|
|
|
bool NetworkUtils::setNetworkInterfaceAlarm(NetworkParams& aOptions)
|
|
{
|
|
DEBUG("setNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
|
|
RUN_CHAIN(aOptions, sNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
|
|
return true;
|
|
}
|
|
|
|
bool NetworkUtils::enableNetworkInterfaceAlarm(NetworkParams& aOptions)
|
|
{
|
|
DEBUG("enableNetworkInterfaceAlarm: %s", GET_CHAR(mIfname));
|
|
RUN_CHAIN(aOptions, sNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
|
|
return true;
|
|
}
|
|
|
|
bool NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions)
|
|
{
|
|
DEBUG("disableNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
|
|
RUN_CHAIN(aOptions, sNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* handling main thread's reload Wifi firmware request
|
|
*/
|
|
bool NetworkUtils::setWifiOperationMode(NetworkParams& aOptions)
|
|
{
|
|
DEBUG("setWifiOperationMode: %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
|
|
RUN_CHAIN(aOptions, sWifiOperationModeChain, wifiOperationModeFail);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* handling main thread's enable/disable WiFi Tethering request
|
|
*/
|
|
bool NetworkUtils::setWifiTethering(NetworkParams& aOptions)
|
|
{
|
|
bool enable = aOptions.mEnable;
|
|
IFProperties interfaceProperties;
|
|
getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
|
|
|
|
if (strcmp(interfaceProperties.dns1, "")) {
|
|
aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
|
|
}
|
|
if (strcmp(interfaceProperties.dns2, "")) {
|
|
aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
|
|
}
|
|
dumpParams(aOptions, "WIFI");
|
|
|
|
if (enable) {
|
|
DEBUG("Starting Wifi Tethering on %s <-> %s",
|
|
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
|
|
RUN_CHAIN(aOptions, sWifiEnableChain, wifiTetheringFail)
|
|
} else {
|
|
DEBUG("Stopping Wifi Tethering on %s <-> %s",
|
|
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
|
|
RUN_CHAIN(aOptions, sWifiDisableChain, wifiTetheringFail)
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool NetworkUtils::setUSBTethering(NetworkParams& aOptions)
|
|
{
|
|
bool enable = aOptions.mEnable;
|
|
IFProperties interfaceProperties;
|
|
getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
|
|
|
|
if (strcmp(interfaceProperties.dns1, "")) {
|
|
aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
|
|
}
|
|
if (strcmp(interfaceProperties.dns2, "")) {
|
|
aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
|
|
}
|
|
dumpParams(aOptions, "USB");
|
|
|
|
if (enable) {
|
|
DEBUG("Starting USB Tethering on %s <-> %s",
|
|
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
|
|
RUN_CHAIN(aOptions, sUSBEnableChain, usbTetheringFail)
|
|
} else {
|
|
DEBUG("Stopping USB Tethering on %s <-> %s",
|
|
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
|
|
RUN_CHAIN(aOptions, sUSBDisableChain, usbTetheringFail)
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void NetworkUtils::checkUsbRndisState(NetworkParams& aOptions)
|
|
{
|
|
static uint32_t retry = 0;
|
|
|
|
char currentState[PROPERTY_VALUE_MAX];
|
|
property_get(SYS_USB_STATE_PROPERTY, currentState, nullptr);
|
|
|
|
nsTArray<nsCString> stateFuncs;
|
|
split(currentState, USB_CONFIG_DELIMIT, stateFuncs);
|
|
bool rndisPresent = stateFuncs.Contains(nsCString(USB_FUNCTION_RNDIS));
|
|
|
|
if (aOptions.mEnable == rndisPresent) {
|
|
NetworkResultOptions result;
|
|
result.mEnable = aOptions.mEnable;
|
|
result.mResult = true;
|
|
postMessage(aOptions, result);
|
|
retry = 0;
|
|
return;
|
|
}
|
|
if (retry < USB_FUNCTION_RETRY_TIMES) {
|
|
retry++;
|
|
usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
|
|
checkUsbRndisState(aOptions);
|
|
return;
|
|
}
|
|
|
|
NetworkResultOptions result;
|
|
result.mResult = false;
|
|
postMessage(aOptions, result);
|
|
retry = 0;
|
|
}
|
|
|
|
/**
|
|
* Modify usb function's property to turn on USB RNDIS function
|
|
*/
|
|
bool NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
|
|
{
|
|
bool report = aOptions.mReport;
|
|
|
|
// For some reason, rndis doesn't play well with diag,modem,nmea.
|
|
// So when turning rndis on, we set sys.usb.config to either "rndis"
|
|
// or "rndis,adb". When turning rndis off, we go back to
|
|
// persist.sys.usb.config.
|
|
//
|
|
// On the otoro/unagi, persist.sys.usb.config should be one of:
|
|
//
|
|
// diag,modem,nmea,mass_storage
|
|
// diag,modem,nmea,mass_storage,adb
|
|
//
|
|
// When rndis is enabled, sys.usb.config should be one of:
|
|
//
|
|
// rdnis
|
|
// rndis,adb
|
|
//
|
|
// and when rndis is disabled, it should revert to persist.sys.usb.config
|
|
|
|
char currentConfig[PROPERTY_VALUE_MAX];
|
|
property_get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
|
|
|
|
nsTArray<nsCString> configFuncs;
|
|
split(currentConfig, USB_CONFIG_DELIMIT, configFuncs);
|
|
|
|
char persistConfig[PROPERTY_VALUE_MAX];
|
|
property_get(PERSIST_SYS_USB_CONFIG_PROPERTY, persistConfig, nullptr);
|
|
|
|
nsTArray<nsCString> persistFuncs;
|
|
split(persistConfig, USB_CONFIG_DELIMIT, persistFuncs);
|
|
|
|
if (aOptions.mEnable) {
|
|
configFuncs.Clear();
|
|
configFuncs.AppendElement(nsCString(USB_FUNCTION_RNDIS));
|
|
if (persistFuncs.Contains(nsCString(USB_FUNCTION_ADB))) {
|
|
configFuncs.AppendElement(nsCString(USB_FUNCTION_ADB));
|
|
}
|
|
} else {
|
|
// We're turning rndis off, revert back to the persist setting.
|
|
// adb will already be correct there, so we don't need to do any
|
|
// further adjustments.
|
|
configFuncs = persistFuncs;
|
|
}
|
|
|
|
char newConfig[PROPERTY_VALUE_MAX] = "";
|
|
property_get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
|
|
join(configFuncs, USB_CONFIG_DELIMIT, PROPERTY_VALUE_MAX, newConfig);
|
|
if (strcmp(currentConfig, newConfig)) {
|
|
property_set(SYS_USB_CONFIG_PROPERTY, newConfig);
|
|
}
|
|
|
|
// Trigger the timer to check usb state and report the result to NetworkManager.
|
|
if (report) {
|
|
usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
|
|
checkUsbRndisState(aOptions);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* handling upstream interface change event.
|
|
*/
|
|
bool NetworkUtils::updateUpStream(NetworkParams& aOptions)
|
|
{
|
|
RUN_CHAIN(aOptions, sUpdateUpStreamChain, updateUpStreamFail)
|
|
return true;
|
|
}
|
|
|
|
void NetworkUtils::sendBroadcastMessage(uint32_t code, char* reason)
|
|
{
|
|
NetworkResultOptions result;
|
|
switch(code) {
|
|
case NETD_COMMAND_INTERFACE_CHANGE:
|
|
result.mTopic = NS_ConvertUTF8toUTF16("netd-interface-change");
|
|
break;
|
|
case NETD_COMMAND_BANDWIDTH_CONTROLLER:
|
|
result.mTopic = NS_ConvertUTF8toUTF16("netd-bandwidth-control");
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
result.mBroadcast = true;
|
|
result.mReason = NS_ConvertUTF8toUTF16(reason);
|
|
postMessage(result);
|
|
}
|
|
|
|
inline uint32_t NetworkUtils::netdResponseType(uint32_t code)
|
|
{
|
|
return (code / 100) * 100;
|
|
}
|
|
|
|
inline bool NetworkUtils::isBroadcastMessage(uint32_t code)
|
|
{
|
|
uint32_t type = netdResponseType(code);
|
|
return type == NETD_COMMAND_UNSOLICITED;
|
|
}
|
|
|
|
inline bool NetworkUtils::isError(uint32_t code)
|
|
{
|
|
uint32_t type = netdResponseType(code);
|
|
return type != NETD_COMMAND_PROCEEDING && type != NETD_COMMAND_OKAY;
|
|
}
|
|
|
|
inline bool NetworkUtils::isComplete(uint32_t code)
|
|
{
|
|
uint32_t type = netdResponseType(code);
|
|
return type != NETD_COMMAND_PROCEEDING;
|
|
}
|
|
|
|
inline bool NetworkUtils::isProceeding(uint32_t code)
|
|
{
|
|
uint32_t type = netdResponseType(code);
|
|
return type == NETD_COMMAND_PROCEEDING;
|
|
}
|
|
|
|
void NetworkUtils::dumpParams(NetworkParams& aOptions, const char* aType)
|
|
{
|
|
#ifdef _DEBUG
|
|
DEBUG("Dump params:");
|
|
DEBUG(" ifname: %s", GET_CHAR(mIfname));
|
|
DEBUG(" ip: %s", GET_CHAR(mIp));
|
|
DEBUG(" link: %s", GET_CHAR(mLink));
|
|
DEBUG(" prefix: %s", GET_CHAR(mPrefix));
|
|
DEBUG(" wifiStartIp: %s", GET_CHAR(mWifiStartIp));
|
|
DEBUG(" wifiEndIp: %s", GET_CHAR(mWifiEndIp));
|
|
DEBUG(" usbStartIp: %s", GET_CHAR(mUsbStartIp));
|
|
DEBUG(" usbEndIp: %s", GET_CHAR(mUsbEndIp));
|
|
DEBUG(" dnsserver1: %s", GET_CHAR(mDns1));
|
|
DEBUG(" dnsserver2: %s", GET_CHAR(mDns2));
|
|
DEBUG(" internalIfname: %s", GET_CHAR(mInternalIfname));
|
|
DEBUG(" externalIfname: %s", GET_CHAR(mExternalIfname));
|
|
if (!strcmp(aType, "WIFI")) {
|
|
DEBUG(" wifictrlinterfacename: %s", GET_CHAR(mWifictrlinterfacename));
|
|
DEBUG(" ssid: %s", GET_CHAR(mSsid));
|
|
DEBUG(" security: %s", GET_CHAR(mSecurity));
|
|
DEBUG(" key: %s", GET_CHAR(mKey));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#undef GET_CHAR
|