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