dom/system/gonk/NetworkUtils.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* Copyright 2012 Mozilla Foundation and Mozilla contributors
     2  *
     3  * Licensed under the Apache License, Version 2.0 (the "License");
     4  * you may not use this file except in compliance with the License.
     5  * You may obtain a copy of the License at
     6  *
     7  *     http://www.apache.org/licenses/LICENSE-2.0
     8  *
     9  * Unless required by applicable law or agreed to in writing, software
    10  * distributed under the License is distributed on an "AS IS" BASIS,
    11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  * See the License for the specific language governing permissions and
    13  * limitations under the License.
    14  */
    16 #include "NetworkUtils.h"
    18 #include <android/log.h>
    19 #include <cutils/properties.h>
    20 #include <limits>
    21 #include "mozilla/dom/network/NetUtils.h"
    23 #include <sys/types.h>  // struct addrinfo
    24 #include <sys/socket.h> // getaddrinfo(), freeaddrinfo()
    25 #include <netdb.h>
    26 #include <arpa/inet.h>  // inet_ntop()
    28 #define _DEBUG 0
    30 #define WARN(args...)   __android_log_print(ANDROID_LOG_WARN,  "NetworkUtils", ## args)
    31 #define ERROR(args...)  __android_log_print(ANDROID_LOG_ERROR,  "NetworkUtils", ## args)
    33 #if _DEBUG
    34 #define DEBUG(args...)  __android_log_print(ANDROID_LOG_DEBUG, "NetworkUtils" , ## args)
    35 #else
    36 #define DEBUG(args...)
    37 #endif
    39 using namespace mozilla::dom;
    40 using namespace mozilla::ipc;
    42 static const char* PERSIST_SYS_USB_CONFIG_PROPERTY = "persist.sys.usb.config";
    43 static const char* SYS_USB_CONFIG_PROPERTY         = "sys.usb.config";
    44 static const char* SYS_USB_STATE_PROPERTY          = "sys.usb.state";
    46 static const char* USB_FUNCTION_RNDIS  = "rndis";
    47 static const char* USB_FUNCTION_ADB    = "adb";
    49 // Use this command to continue the function chain.
    50 static const char* DUMMY_COMMAND = "tether status";
    52 // Retry 20 times (2 seconds) for usb state transition.
    53 static const uint32_t USB_FUNCTION_RETRY_TIMES = 20;
    54 // Check "sys.usb.state" every 100ms.
    55 static const uint32_t USB_FUNCTION_RETRY_INTERVAL = 100;
    57 // 1xx - Requested action is proceeding
    58 static const uint32_t NETD_COMMAND_PROCEEDING   = 100;
    59 // 2xx - Requested action has been successfully completed
    60 static const uint32_t NETD_COMMAND_OKAY         = 200;
    61 // 4xx - The command is accepted but the requested action didn't
    62 // take place.
    63 static const uint32_t NETD_COMMAND_FAIL         = 400;
    64 // 5xx - The command syntax or parameters error
    65 static const uint32_t NETD_COMMAND_ERROR        = 500;
    66 // 6xx - Unsolicited broadcasts
    67 static const uint32_t NETD_COMMAND_UNSOLICITED  = 600;
    69 // Broadcast messages
    70 static const uint32_t NETD_COMMAND_INTERFACE_CHANGE     = 600;
    71 static const uint32_t NETD_COMMAND_BANDWIDTH_CONTROLLER = 601;
    73 static const char* INTERFACE_DELIMIT = ",";
    74 static const char* USB_CONFIG_DELIMIT = ",";
    75 static const char* NETD_MESSAGE_DELIMIT = " ";
    77 static const uint32_t BUF_SIZE = 1024;
    79 static uint32_t SDK_VERSION;
    81 struct IFProperties {
    82   char gateway[PROPERTY_VALUE_MAX];
    83   char dns1[PROPERTY_VALUE_MAX];
    84   char dns2[PROPERTY_VALUE_MAX];
    85 };
    87 struct CurrentCommand {
    88   CommandChain* chain;
    89   CommandCallback callback;
    90   char command[MAX_COMMAND_SIZE];
    91 };
    93 typedef Tuple3<NetdCommand*, CommandChain*, CommandCallback> QueueData;
    95 #define GET_CURRENT_NETD_COMMAND   (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a)
    96 #define GET_CURRENT_CHAIN          (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].b)
    97 #define GET_CURRENT_CALLBACK       (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].c)
    98 #define GET_CURRENT_COMMAND        (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a->mData)
   100 static NetworkUtils* gNetworkUtils;
   101 static nsTArray<QueueData> gCommandQueue;
   102 static CurrentCommand gCurrentCommand;
   103 static bool gPending = false;
   104 static nsTArray<nsCString> gReason;
   106 CommandFunc NetworkUtils::sWifiEnableChain[] = {
   107   NetworkUtils::wifiFirmwareReload,
   108   NetworkUtils::startAccessPointDriver,
   109   NetworkUtils::setAccessPoint,
   110   NetworkUtils::startSoftAP,
   111   NetworkUtils::setInterfaceUp,
   112   NetworkUtils::tetherInterface,
   113   NetworkUtils::setIpForwardingEnabled,
   114   NetworkUtils::tetheringStatus,
   115   NetworkUtils::startTethering,
   116   NetworkUtils::setDnsForwarders,
   117   NetworkUtils::enableNat,
   118   NetworkUtils::wifiTetheringSuccess
   119 };
   121 CommandFunc NetworkUtils::sWifiDisableChain[] = {
   122   NetworkUtils::stopSoftAP,
   123   NetworkUtils::stopAccessPointDriver,
   124   NetworkUtils::wifiFirmwareReload,
   125   NetworkUtils::untetherInterface,
   126   NetworkUtils::preTetherInterfaceList,
   127   NetworkUtils::postTetherInterfaceList,
   128   NetworkUtils::disableNat,
   129   NetworkUtils::setIpForwardingEnabled,
   130   NetworkUtils::stopTethering,
   131   NetworkUtils::wifiTetheringSuccess
   132 };
   134 CommandFunc NetworkUtils::sWifiFailChain[] = {
   135   NetworkUtils::stopSoftAP,
   136   NetworkUtils::setIpForwardingEnabled,
   137   NetworkUtils::stopTethering
   138 };
   140 CommandFunc NetworkUtils::sWifiOperationModeChain[] = {
   141   NetworkUtils::wifiFirmwareReload,
   142   NetworkUtils::wifiOperationModeSuccess
   143 };
   145 CommandFunc NetworkUtils::sUSBEnableChain[] = {
   146   NetworkUtils::setInterfaceUp,
   147   NetworkUtils::enableNat,
   148   NetworkUtils::setIpForwardingEnabled,
   149   NetworkUtils::tetherInterface,
   150   NetworkUtils::tetheringStatus,
   151   NetworkUtils::startTethering,
   152   NetworkUtils::setDnsForwarders,
   153   NetworkUtils::usbTetheringSuccess
   154 };
   156 CommandFunc NetworkUtils::sUSBDisableChain[] = {
   157   NetworkUtils::untetherInterface,
   158   NetworkUtils::preTetherInterfaceList,
   159   NetworkUtils::postTetherInterfaceList,
   160   NetworkUtils::disableNat,
   161   NetworkUtils::setIpForwardingEnabled,
   162   NetworkUtils::stopTethering,
   163   NetworkUtils::usbTetheringSuccess
   164 };
   166 CommandFunc NetworkUtils::sUSBFailChain[] = {
   167   NetworkUtils::stopSoftAP,
   168   NetworkUtils::setIpForwardingEnabled,
   169   NetworkUtils::stopTethering
   170 };
   172 CommandFunc NetworkUtils::sUpdateUpStreamChain[] = {
   173   NetworkUtils::cleanUpStream,
   174   NetworkUtils::createUpStream,
   175   NetworkUtils::updateUpStreamSuccess
   176 };
   178 CommandFunc NetworkUtils::sStartDhcpServerChain[] = {
   179   NetworkUtils::setInterfaceUp,
   180   NetworkUtils::startTethering,
   181   NetworkUtils::setDhcpServerSuccess
   182 };
   184 CommandFunc NetworkUtils::sStopDhcpServerChain[] = {
   185   NetworkUtils::stopTethering,
   186   NetworkUtils::setDhcpServerSuccess
   187 };
   189 CommandFunc NetworkUtils::sNetworkInterfaceStatsChain[] = {
   190   NetworkUtils::getRxBytes,
   191   NetworkUtils::getTxBytes,
   192   NetworkUtils::networkInterfaceStatsSuccess
   193 };
   195 CommandFunc NetworkUtils::sNetworkInterfaceEnableAlarmChain[] = {
   196   NetworkUtils::enableAlarm,
   197   NetworkUtils::setQuota,
   198   NetworkUtils::setAlarm,
   199   NetworkUtils::networkInterfaceAlarmSuccess
   200 };
   202 CommandFunc NetworkUtils::sNetworkInterfaceDisableAlarmChain[] = {
   203   NetworkUtils::removeQuota,
   204   NetworkUtils::disableAlarm,
   205   NetworkUtils::networkInterfaceAlarmSuccess
   206 };
   208 CommandFunc NetworkUtils::sNetworkInterfaceSetAlarmChain[] = {
   209   NetworkUtils::setAlarm,
   210   NetworkUtils::networkInterfaceAlarmSuccess
   211 };
   213 CommandFunc NetworkUtils::sSetDnsChain[] = {
   214   NetworkUtils::setDefaultInterface,
   215   NetworkUtils::setInterfaceDns
   216 };
   218 /**
   219  * Helper function to get the mask from given prefix length.
   220  */
   221 static uint32_t makeMask(const uint32_t prefixLength)
   222 {
   223   uint32_t mask = 0;
   224   for (uint32_t i = 0; i < prefixLength; ++i) {
   225     mask |= (0x80000000 >> i);
   226   }
   227   return ntohl(mask);
   228 }
   230 /**
   231  * Helper function to get the network part of an ip from prefix.
   232  * param ip must be in network byte order.
   233  */
   234 static char* getNetworkAddr(const uint32_t ip, const uint32_t prefix)
   235 {
   236   uint32_t mask = 0, subnet = 0;
   238   mask = ~mask << (32 - prefix);
   239   mask = htonl(mask);
   240   subnet = ip & mask;
   242   struct in_addr addr;
   243   addr.s_addr = subnet;
   245   return inet_ntoa(addr);
   246 }
   248 /**
   249  * Helper function to split string by seperator, store split result as an nsTArray.
   250  */
   251 static void split(char* str, const char* sep, nsTArray<nsCString>& result)
   252 {
   253   char *s = strtok(str, sep);
   254   while (s != nullptr) {
   255     result.AppendElement(s);
   256     s = strtok(nullptr, sep);
   257   }
   258 }
   260 static void split(char* str, const char* sep, nsTArray<nsString>& result)
   261 {
   262   char *s = strtok(str, sep);
   263   while (s != nullptr) {
   264     result.AppendElement(NS_ConvertUTF8toUTF16(s));
   265     s = strtok(nullptr, sep);
   266   }
   267 }
   269 /**
   270  * Helper function that implement join function.
   271  */
   272 static void join(nsTArray<nsCString>& array,
   273                  const char* sep,
   274                  const uint32_t maxlen,
   275                  char* result)
   276 {
   277 #define CHECK_LENGTH(len, add, max)  len += add;          \
   278                                      if (len > max - 1)   \
   279                                        return;            \
   281   uint32_t len = 0;
   282   uint32_t seplen = strlen(sep);
   284   if (array.Length() > 0) {
   285     CHECK_LENGTH(len, strlen(array[0].get()), maxlen)
   286     strcpy(result, array[0].get());
   288     for (uint32_t i = 1; i < array.Length(); i++) {
   289       CHECK_LENGTH(len, seplen, maxlen)
   290       strcat(result, sep);
   292       CHECK_LENGTH(len, strlen(array[i].get()), maxlen)
   293       strcat(result, array[i].get());
   294     }
   295   }
   297 #undef CHECK_LEN
   298 }
   300 /**
   301  * Helper function to get network interface properties from the system property table.
   302  */
   303 static void getIFProperties(const char* ifname, IFProperties& prop)
   304 {
   305   char key[PROPERTY_KEY_MAX];
   306   snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.gw", ifname);
   307   property_get(key, prop.gateway, "");
   308   snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.dns1", ifname);
   309   property_get(key, prop.dns1, "");
   310   snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.dns2", ifname);
   311   property_get(key, prop.dns2, "");
   312 }
   314 static int getIpType(const char *aIp) {
   315   struct addrinfo hint, *ip_info = NULL;
   317   memset(&hint, 0, sizeof(hint));
   318   hint.ai_family = AF_UNSPEC;
   319   hint.ai_flags = AI_NUMERICHOST;
   321   if (getaddrinfo(aIp, NULL, &hint, &ip_info)) {
   322     return AF_UNSPEC;
   323   }
   325   int type = ip_info->ai_family;
   326   freeaddrinfo(ip_info);
   328   return type;
   329 }
   331 /**
   332  * Helper function to find the best match gateway. For now, return
   333  * the gateway that matches the address family passed.
   334  */
   335 static uint32_t selectGateway(nsTArray<nsString>& gateways, int addrFamily)
   336 {
   337   uint32_t length = gateways.Length();
   339   for (uint32_t i = 0; i < length; i++) {
   340     NS_ConvertUTF16toUTF8 autoGateway(gateways[i]);
   341     if ((getIpType(autoGateway.get()) == AF_INET && addrFamily == AF_INET) ||
   342         (getIpType(autoGateway.get()) == AF_INET6 && addrFamily == AF_INET6)) {
   343       return i;
   344     }
   345   }
   346   return length; // invalid index.
   347 }
   349 static void postMessage(NetworkResultOptions& aResult)
   350 {
   351   MOZ_ASSERT(gNetworkUtils);
   352   MOZ_ASSERT(gNetworkUtils->getMessageCallback());
   354   if (*(gNetworkUtils->getMessageCallback()))
   355     (*(gNetworkUtils->getMessageCallback()))(aResult);
   356 }
   358 static void postMessage(NetworkParams& aOptions, NetworkResultOptions& aResult)
   359 {
   360   MOZ_ASSERT(gNetworkUtils);
   361   MOZ_ASSERT(gNetworkUtils->getMessageCallback());
   363   aResult.mId = aOptions.mId;
   365   if (*(gNetworkUtils->getMessageCallback()))
   366     (*(gNetworkUtils->getMessageCallback()))(aResult);
   367 }
   369 void NetworkUtils::next(CommandChain* aChain, bool aError, NetworkResultOptions& aResult)
   370 {
   371   if (aError) {
   372     ErrorCallback onError = aChain->getErrorCallback();
   373     if(onError) {
   374       aResult.mError = true;
   375       (*onError)(aChain->getParams(), aResult);
   376     }
   377     delete aChain;
   378     return;
   379   }
   380   CommandFunc f = aChain->getNextCommand();
   381   if (!f) {
   382     delete aChain;
   383     return;
   384   }
   386   (*f)(aChain, next, aResult);
   387 }
   389 /**
   390  * Send command to netd.
   391  */
   392 void NetworkUtils::nextNetdCommand()
   393 {
   394   if (gCommandQueue.IsEmpty() || gPending) {
   395     return;
   396   }
   398   gCurrentCommand.chain = GET_CURRENT_CHAIN;
   399   gCurrentCommand.callback = GET_CURRENT_CALLBACK;
   400   snprintf(gCurrentCommand.command, MAX_COMMAND_SIZE - 1, "%s", GET_CURRENT_COMMAND);
   402   DEBUG("Sending \'%s\' command to netd.", gCurrentCommand.command);
   403   SendNetdCommand(GET_CURRENT_NETD_COMMAND);
   405   gCommandQueue.RemoveElementAt(0);
   406   gPending = true;
   407 }
   409 /**
   410  * Composite NetdCommand sent to netd
   411  *
   412  * @param aCommand  Command sent to netd to execute.
   413  * @param aChain    Store command chain data, ex. command parameter.
   414  * @param aCallback Callback function to be executed when the result of
   415  *                  this command is returned from netd.
   416  */
   417 void NetworkUtils::doCommand(const char* aCommand, CommandChain* aChain, CommandCallback aCallback)
   418 {
   419   DEBUG("Preparing to send \'%s\' command...", aCommand);
   421   NetdCommand* netdCommand = new NetdCommand();
   423   // Android JB version adds sequence number to netd command.
   424   if (SDK_VERSION >= 16) {
   425     snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "0 %s", aCommand);
   426   } else {
   427     snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "%s", aCommand);
   428   }
   429   netdCommand->mSize = strlen((char*)netdCommand->mData) + 1;
   431   gCommandQueue.AppendElement(QueueData(netdCommand, aChain, aCallback));
   433   nextNetdCommand();
   434 }
   436 /*
   437  * Netd command function
   438  */
   439 #define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aChain->getParams().prop).get()
   440 #define GET_FIELD(prop) aChain->getParams().prop
   442 void NetworkUtils::wifiFirmwareReload(CommandChain* aChain,
   443                                       CommandCallback aCallback,
   444                                       NetworkResultOptions& aResult)
   445 {
   446   char command[MAX_COMMAND_SIZE];
   447   snprintf(command, MAX_COMMAND_SIZE - 1, "softap fwreload %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
   449   doCommand(command, aChain, aCallback);
   450 }
   452 void NetworkUtils::startAccessPointDriver(CommandChain* aChain,
   453                                           CommandCallback aCallback,
   454                                           NetworkResultOptions& aResult)
   455 {
   456   // Skip the command for sdk version >= 16.
   457   if (SDK_VERSION >= 16) {
   458     aResult.mResultCode = 0;
   459     aResult.mResultReason = NS_ConvertUTF8toUTF16("");
   460     aCallback(aChain, false, aResult);
   461     return;
   462   }
   464   char command[MAX_COMMAND_SIZE];
   465   snprintf(command, MAX_COMMAND_SIZE - 1, "softap start %s", GET_CHAR(mIfname));
   467   doCommand(command, aChain, aCallback);
   468 }
   470 void NetworkUtils::stopAccessPointDriver(CommandChain* aChain,
   471                                          CommandCallback aCallback,
   472                                          NetworkResultOptions& aResult)
   473 {
   474   // Skip the command for sdk version >= 16.
   475   if (SDK_VERSION >= 16) {
   476     aResult.mResultCode = 0;
   477     aResult.mResultReason = NS_ConvertUTF8toUTF16("");
   478     aCallback(aChain, false, aResult);
   479     return;
   480   }
   482   char command[MAX_COMMAND_SIZE];
   483   snprintf(command, MAX_COMMAND_SIZE - 1, "softap stop %s", GET_CHAR(mIfname));
   485   doCommand(command, aChain, aCallback);
   486 }
   488 /**
   489  * Command format for sdk version < 16
   490  *   Arguments:
   491  *     argv[2] - wlan interface
   492  *     argv[3] - SSID
   493  *     argv[4] - Security
   494  *     argv[5] - Key
   495  *     argv[6] - Channel
   496  *     argv[7] - Preamble
   497  *     argv[8] - Max SCB
   498  *
   499  * Command format for sdk version >= 16
   500  *   Arguments:
   501  *     argv[2] - wlan interface
   502  *     argv[3] - SSID
   503  *     argv[4] - Security
   504  *     argv[5] - Key
   505  *
   506  * Command format for sdk version >= 18
   507  *   Arguments:
   508  *      argv[2] - wlan interface
   509  *      argv[3] - SSID
   510  *      argv[4] - Broadcast/Hidden
   511  *      argv[5] - Channel
   512  *      argv[6] - Security
   513  *      argv[7] - Key
   514  */
   515 void NetworkUtils::setAccessPoint(CommandChain* aChain,
   516                                   CommandCallback aCallback,
   517                                   NetworkResultOptions& aResult)
   518 {
   519   char command[MAX_COMMAND_SIZE];
   520   nsCString ssid(GET_CHAR(mSsid));
   521   nsCString key(GET_CHAR(mKey));
   523   escapeQuote(ssid);
   524   escapeQuote(key);
   526   if (SDK_VERSION >= 19) {
   527     snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" broadcast 6 %s \"%s\"",
   528                      GET_CHAR(mIfname),
   529                      ssid.get(),
   530                      GET_CHAR(mSecurity),
   531                      key.get());
   532   } else if (SDK_VERSION >= 16) {
   533     snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" %s \"%s\"",
   534                      GET_CHAR(mIfname),
   535                      ssid.get(),
   536                      GET_CHAR(mSecurity),
   537                      key.get());
   538   } else {
   539     snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s %s \"%s\" %s \"%s\" 6 0 8",
   540                      GET_CHAR(mIfname),
   541                      GET_CHAR(mWifictrlinterfacename),
   542                      ssid.get(),
   543                      GET_CHAR(mSecurity),
   544                      key.get());
   545   }
   547   doCommand(command, aChain, aCallback);
   548 }
   550 void NetworkUtils::cleanUpStream(CommandChain* aChain,
   551                                  CommandCallback aCallback,
   552                                  NetworkResultOptions& aResult)
   553 {
   554   char command[MAX_COMMAND_SIZE];
   555   snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0", GET_CHAR(mPreInternalIfname), GET_CHAR(mPreExternalIfname));
   557   doCommand(command, aChain, aCallback);
   558 }
   560 void NetworkUtils::createUpStream(CommandChain* aChain,
   561                                   CommandCallback aCallback,
   562                                   NetworkResultOptions& aResult)
   563 {
   564   char command[MAX_COMMAND_SIZE];
   565   snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0", GET_CHAR(mCurInternalIfname), GET_CHAR(mCurExternalIfname));
   567   doCommand(command, aChain, aCallback);
   568 }
   570 void NetworkUtils::startSoftAP(CommandChain* aChain,
   571                                CommandCallback aCallback,
   572                                NetworkResultOptions& aResult)
   573 {
   574   const char* command= "softap startap";
   575   doCommand(command, aChain, aCallback);
   576 }
   578 void NetworkUtils::stopSoftAP(CommandChain* aChain,
   579                               CommandCallback aCallback,
   580                               NetworkResultOptions& aResult)
   581 {
   582   const char* command= "softap stopap";
   583   doCommand(command, aChain, aCallback);
   584 }
   586 void NetworkUtils::getRxBytes(CommandChain* aChain,
   587                               CommandCallback aCallback,
   588                               NetworkResultOptions& aResult)
   589 {
   590   char command[MAX_COMMAND_SIZE];
   591   snprintf(command, MAX_COMMAND_SIZE - 1, "interface readrxcounter %s", GET_CHAR(mIfname));
   593   doCommand(command, aChain, aCallback);
   594 }
   596 void NetworkUtils::getTxBytes(CommandChain* aChain,
   597                               CommandCallback aCallback,
   598                               NetworkResultOptions& aResult)
   599 {
   600   NetworkParams& options = aChain->getParams();
   601   options.mRxBytes = atof(NS_ConvertUTF16toUTF8(aResult.mResultReason).get());
   603   char command[MAX_COMMAND_SIZE];
   604   snprintf(command, MAX_COMMAND_SIZE - 1, "interface readtxcounter %s", GET_CHAR(mIfname));
   606   doCommand(command, aChain, aCallback);
   607 }
   609 void NetworkUtils::enableAlarm(CommandChain* aChain,
   610                                CommandCallback aCallback,
   611                                NetworkResultOptions& aResult)
   612 {
   613   const char* command= "bandwidth enable";
   614   doCommand(command, aChain, aCallback);
   615 }
   617 void NetworkUtils::disableAlarm(CommandChain* aChain,
   618                                 CommandCallback aCallback,
   619                                 NetworkResultOptions& aResult)
   620 {
   621   const char* command= "bandwidth disable";
   622   doCommand(command, aChain, aCallback);
   623 }
   625 void NetworkUtils::setQuota(CommandChain* aChain,
   626                             CommandCallback aCallback,
   627                             NetworkResultOptions& aResult)
   628 {
   629   char command[MAX_COMMAND_SIZE];
   630   snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setiquota %s %lld", GET_CHAR(mIfname), LLONG_MAX);
   632   doCommand(command, aChain, aCallback);
   633 }
   635 void NetworkUtils::removeQuota(CommandChain* aChain,
   636                                CommandCallback aCallback,
   637                                NetworkResultOptions& aResult)
   638 {
   639   char command[MAX_COMMAND_SIZE];
   640   snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeiquota %s", GET_CHAR(mIfname));
   642   doCommand(command, aChain, aCallback);
   643 }
   645 void NetworkUtils::setAlarm(CommandChain* aChain,
   646                             CommandCallback aCallback,
   647                             NetworkResultOptions& aResult)
   648 {
   649   char command[MAX_COMMAND_SIZE];
   650   snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setinterfacealert %s %ld", GET_CHAR(mIfname), GET_FIELD(mThreshold));
   652   doCommand(command, aChain, aCallback);
   653 }
   655 void NetworkUtils::setInterfaceUp(CommandChain* aChain,
   656                                   CommandCallback aCallback,
   657                                   NetworkResultOptions& aResult)
   658 {
   659   char command[MAX_COMMAND_SIZE];
   660   if (SDK_VERSION >= 16) {
   661     snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s %s",
   662                      GET_CHAR(mIfname),
   663                      GET_CHAR(mIp),
   664                      GET_CHAR(mPrefix),
   665                      GET_CHAR(mLink));
   666   } else {
   667     snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s [%s]",
   668                      GET_CHAR(mIfname),
   669                      GET_CHAR(mIp),
   670                      GET_CHAR(mPrefix),
   671                      GET_CHAR(mLink));
   672   }
   673   doCommand(command, aChain, aCallback);
   674 }
   676 void NetworkUtils::tetherInterface(CommandChain* aChain,
   677                                    CommandCallback aCallback,
   678                                    NetworkResultOptions& aResult)
   679 {
   680   char command[MAX_COMMAND_SIZE];
   681   snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface add %s", GET_CHAR(mIfname));
   683   doCommand(command, aChain, aCallback);
   684 }
   686 void NetworkUtils::preTetherInterfaceList(CommandChain* aChain,
   687                                           CommandCallback aCallback,
   688                                           NetworkResultOptions& aResult)
   689 {
   690   char command[MAX_COMMAND_SIZE];
   691   if (SDK_VERSION >= 16) {
   692     snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list");
   693   } else {
   694     snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list 0");
   695   }
   697   doCommand(command, aChain, aCallback);
   698 }
   700 void NetworkUtils::postTetherInterfaceList(CommandChain* aChain,
   701                                            CommandCallback aCallback,
   702                                            NetworkResultOptions& aResult)
   703 {
   704   // Send the dummy command to continue the function chain.
   705   char command[MAX_COMMAND_SIZE];
   706   snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
   708   char buf[BUF_SIZE];
   709   const char* reason = NS_ConvertUTF16toUTF8(aResult.mResultReason).get();
   710   memcpy(buf, reason, strlen(reason));
   711   split(buf, INTERFACE_DELIMIT, GET_FIELD(mInterfaceList));
   713   doCommand(command, aChain, aCallback);
   714 }
   716 void NetworkUtils::setIpForwardingEnabled(CommandChain* aChain,
   717                                           CommandCallback aCallback,
   718                                           NetworkResultOptions& aResult)
   719 {
   720   char command[MAX_COMMAND_SIZE];
   722   if (GET_FIELD(mEnable)) {
   723     snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd enable");
   724   } else {
   725     // Don't disable ip forwarding because others interface still need it.
   726     // Send the dummy command to continue the function chain.
   727     if (GET_FIELD(mInterfaceList).Length() > 1) {
   728       snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
   729     } else {
   730       snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd disable");
   731     }
   732   }
   734   doCommand(command, aChain, aCallback);
   735 }
   737 void NetworkUtils::tetheringStatus(CommandChain* aChain,
   738                                    CommandCallback aCallback,
   739                                    NetworkResultOptions& aResult)
   740 {
   741   const char* command= "tether status";
   742   doCommand(command, aChain, aCallback);
   743 }
   745 void NetworkUtils::stopTethering(CommandChain* aChain,
   746                                  CommandCallback aCallback,
   747                                  NetworkResultOptions& aResult)
   748 {
   749   char command[MAX_COMMAND_SIZE];
   751   // Don't stop tethering because others interface still need it.
   752   // Send the dummy to continue the function chain.
   753   if (GET_FIELD(mInterfaceList).Length() > 1) {
   754     snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
   755   } else {
   756     snprintf(command, MAX_COMMAND_SIZE - 1, "tether stop");
   757   }
   759   doCommand(command, aChain, aCallback);
   760 }
   762 void NetworkUtils::startTethering(CommandChain* aChain,
   763                                   CommandCallback aCallback,
   764                                   NetworkResultOptions& aResult)
   765 {
   766   char command[MAX_COMMAND_SIZE];
   768   // We don't need to start tethering again.
   769   // Send the dummy command to continue the function chain.
   770   if (aResult.mResultReason.Find("started") != kNotFound) {
   771     snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
   772   } else {
   773     snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s", GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp));
   775     // If usbStartIp/usbEndIp is not valid, don't append them since
   776     // the trailing white spaces will be parsed to extra empty args
   777     // See: http://androidxref.com/4.3_r2.1/xref/system/core/libsysutils/src/FrameworkListener.cpp#78
   778     if (!GET_FIELD(mUsbStartIp).IsEmpty() && !GET_FIELD(mUsbEndIp).IsEmpty()) {
   779       snprintf(command, MAX_COMMAND_SIZE - 1, "%s %s %s", command, GET_CHAR(mUsbStartIp), GET_CHAR(mUsbEndIp));
   780     }
   781   }
   783   doCommand(command, aChain, aCallback);
   784 }
   786 void NetworkUtils::untetherInterface(CommandChain* aChain,
   787                                      CommandCallback aCallback,
   788                                      NetworkResultOptions& aResult)
   789 {
   790   char command[MAX_COMMAND_SIZE];
   791   snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface remove %s", GET_CHAR(mIfname));
   793   doCommand(command, aChain, aCallback);
   794 }
   796 void NetworkUtils::setDnsForwarders(CommandChain* aChain,
   797                                     CommandCallback aCallback,
   798                                     NetworkResultOptions& aResult)
   799 {
   800   char command[MAX_COMMAND_SIZE];
   801   snprintf(command, MAX_COMMAND_SIZE - 1, "tether dns set %s %s", GET_CHAR(mDns1), GET_CHAR(mDns2));
   803   doCommand(command, aChain, aCallback);
   804 }
   806 void NetworkUtils::enableNat(CommandChain* aChain,
   807                              CommandCallback aCallback,
   808                              NetworkResultOptions& aResult)
   809 {
   810   char command[MAX_COMMAND_SIZE];
   812   if (!GET_FIELD(mIp).IsEmpty() && !GET_FIELD(mPrefix).IsEmpty()) {
   813     uint32_t prefix = atoi(GET_CHAR(mPrefix));
   814     uint32_t ip = inet_addr(GET_CHAR(mIp));
   815     char* networkAddr = getNetworkAddr(ip, prefix);
   817     // address/prefix will only take effect when secondary routing table exists.
   818     snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 1 %s/%s",
   819       GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname), networkAddr,
   820       GET_CHAR(mPrefix));
   821   } else {
   822     snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0",
   823       GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
   824   }
   826   doCommand(command, aChain, aCallback);
   827 }
   829 void NetworkUtils::disableNat(CommandChain* aChain,
   830                               CommandCallback aCallback,
   831                               NetworkResultOptions& aResult)
   832 {
   833   char command[MAX_COMMAND_SIZE];
   835   if (!GET_FIELD(mIp).IsEmpty() && !GET_FIELD(mPrefix).IsEmpty()) {
   836     uint32_t prefix = atoi(GET_CHAR(mPrefix));
   837     uint32_t ip = inet_addr(GET_CHAR(mIp));
   838     char* networkAddr = getNetworkAddr(ip, prefix);
   840     snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 1 %s/%s",
   841       GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname), networkAddr,
   842       GET_CHAR(mPrefix));
   843   } else {
   844     snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0",
   845       GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
   846   }
   848   doCommand(command, aChain, aCallback);
   849 }
   851 void NetworkUtils::setDefaultInterface(CommandChain* aChain,
   852                                        CommandCallback aCallback,
   853                                        NetworkResultOptions& aResult)
   854 {
   855   char command[MAX_COMMAND_SIZE];
   856   snprintf(command, MAX_COMMAND_SIZE - 1, "resolver setdefaultif %s", GET_CHAR(mIfname));
   858   doCommand(command, aChain, aCallback);
   859 }
   861 void NetworkUtils::setInterfaceDns(CommandChain* aChain,
   862                                    CommandCallback aCallback,
   863                                    NetworkResultOptions& aResult)
   864 {
   865   char command[MAX_COMMAND_SIZE];
   866   int written = snprintf(command, sizeof command, "resolver setifdns %s %s",
   867                          GET_CHAR(mIfname), GET_CHAR(mDomain));
   869   nsTArray<nsString>& dnses = GET_FIELD(mDnses);
   870   uint32_t length = dnses.Length();
   872   for (uint32_t i = 0; i < length; i++) {
   873     NS_ConvertUTF16toUTF8 autoDns(dnses[i]);
   875     int ret = snprintf(command + written, sizeof(command) - written, " %s", autoDns.get());
   876     if (ret <= 1) {
   877       command[written] = '\0';
   878       continue;
   879     }
   881     if ((ret + written) >= sizeof(command)) {
   882       command[written] = '\0';
   883       break;
   884     }
   886     written += ret;
   887   }
   889   doCommand(command, aChain, aCallback);
   890 }
   892 #undef GET_CHAR
   893 #undef GET_FIELD
   895 /*
   896  * Netd command success/fail function
   897  */
   898 #define ASSIGN_FIELD(prop)  aResult.prop = aChain->getParams().prop;
   899 #define ASSIGN_FIELD_VALUE(prop, value)  aResult.prop = value;
   901 #define RUN_CHAIN(param, cmds, err)                                \
   902   uint32_t size = sizeof(cmds) / sizeof(CommandFunc);              \
   903   CommandChain* chain = new CommandChain(param, cmds, size, err);  \
   904   NetworkResultOptions result;                                     \
   905   next(chain, false, result);
   907 void NetworkUtils::wifiTetheringFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
   908 {
   909   // Notify the main thread.
   910   postMessage(aOptions, aResult);
   912   // If one of the stages fails, we try roll back to ensure
   913   // we don't leave the network systems in limbo.
   914   ASSIGN_FIELD_VALUE(mEnable, false)
   915   RUN_CHAIN(aOptions, sWifiFailChain, nullptr)
   916 }
   918 void NetworkUtils::wifiTetheringSuccess(CommandChain* aChain,
   919                                         CommandCallback aCallback,
   920                                         NetworkResultOptions& aResult)
   921 {
   922   ASSIGN_FIELD(mEnable)
   923   postMessage(aChain->getParams(), aResult);
   924 }
   926 void NetworkUtils::usbTetheringFail(NetworkParams& aOptions,
   927                                     NetworkResultOptions& aResult)
   928 {
   929   // Notify the main thread.
   930   postMessage(aOptions, aResult);
   931   // Try to roll back to ensure
   932   // we don't leave the network systems in limbo.
   933   // This parameter is used to disable ipforwarding.
   934   {
   935     aOptions.mEnable = false;
   936     RUN_CHAIN(aOptions, sUSBFailChain, nullptr)
   937   }
   939   // Disable usb rndis function.
   940   {
   941     NetworkParams options;
   942     options.mEnable = false;
   943     options.mReport = false;
   944     gNetworkUtils->enableUsbRndis(options);
   945   }
   946 }
   948 void NetworkUtils::usbTetheringSuccess(CommandChain* aChain,
   949                                        CommandCallback aCallback,
   950                                        NetworkResultOptions& aResult)
   951 {
   952   ASSIGN_FIELD(mEnable)
   953   postMessage(aChain->getParams(), aResult);
   954 }
   956 void NetworkUtils::networkInterfaceStatsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
   957 {
   958   postMessage(aOptions, aResult);
   959 }
   961 void NetworkUtils::networkInterfaceStatsSuccess(CommandChain* aChain,
   962                                                 CommandCallback aCallback,
   963                                                 NetworkResultOptions& aResult)
   964 {
   965   ASSIGN_FIELD(mRxBytes)
   966   ASSIGN_FIELD_VALUE(mTxBytes, atof(NS_ConvertUTF16toUTF8(aResult.mResultReason).get()))
   967   postMessage(aChain->getParams(), aResult);
   968 }
   970 void NetworkUtils::networkInterfaceAlarmFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
   971 {
   972   postMessage(aOptions, aResult);
   973 }
   975 void NetworkUtils::networkInterfaceAlarmSuccess(CommandChain* aChain,
   976                                                 CommandCallback aCallback,
   977                                                 NetworkResultOptions& aResult)
   978 {
   979   // TODO : error is not used , and it is conflict with boolean type error.
   980   // params.error = parseFloat(params.resultReason);
   981   postMessage(aChain->getParams(), aResult);
   982 }
   984 void NetworkUtils::updateUpStreamFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
   985 {
   986   postMessage(aOptions, aResult);
   987 }
   989 void NetworkUtils::updateUpStreamSuccess(CommandChain* aChain,
   990                                          CommandCallback aCallback,
   991                                          NetworkResultOptions& aResult)
   992 {
   993   ASSIGN_FIELD(mCurExternalIfname)
   994   ASSIGN_FIELD(mCurInternalIfname)
   995   postMessage(aChain->getParams(), aResult);
   996 }
   998 void NetworkUtils::setDhcpServerFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
   999 {
  1000   aResult.mSuccess = false;
  1001   postMessage(aOptions, aResult);
  1004 void NetworkUtils::setDhcpServerSuccess(CommandChain* aChain, CommandCallback aCallback, NetworkResultOptions& aResult)
  1006   aResult.mSuccess = true;
  1007   postMessage(aChain->getParams(), aResult);
  1010 void NetworkUtils::wifiOperationModeFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
  1012   postMessage(aOptions, aResult);
  1015 void NetworkUtils::wifiOperationModeSuccess(CommandChain* aChain,
  1016                                             CommandCallback aCallback,
  1017                                             NetworkResultOptions& aResult)
  1019   postMessage(aChain->getParams(), aResult);
  1022 void NetworkUtils::setDnsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
  1024   postMessage(aOptions, aResult);
  1027 #undef ASSIGN_FIELD
  1028 #undef ASSIGN_FIELD_VALUE
  1030 NetworkUtils::NetworkUtils(MessageCallback aCallback)
  1031  : mMessageCallback(aCallback)
  1033   mNetUtils = new NetUtils();
  1035   char value[PROPERTY_VALUE_MAX];
  1036   property_get("ro.build.version.sdk", value, nullptr);
  1037   SDK_VERSION = atoi(value);
  1039   gNetworkUtils = this;
  1042 NetworkUtils::~NetworkUtils()
  1046 #define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aOptions.prop).get()
  1047 #define GET_FIELD(prop) aOptions.prop
  1049 void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
  1051   bool ret = true;
  1053   if (aOptions.mCmd.EqualsLiteral("removeNetworkRoute")) {
  1054     removeNetworkRoute(aOptions);
  1055   } else if (aOptions.mCmd.EqualsLiteral("setDNS")) {
  1056     setDNS(aOptions);
  1057   } else if (aOptions.mCmd.EqualsLiteral("setDefaultRouteAndDNS")) {
  1058     setDefaultRouteAndDNS(aOptions);
  1059   } else if (aOptions.mCmd.EqualsLiteral("removeDefaultRoute")) {
  1060     removeDefaultRoute(aOptions);
  1061   } else if (aOptions.mCmd.EqualsLiteral("addHostRoute")) {
  1062     addHostRoute(aOptions);
  1063   } else if (aOptions.mCmd.EqualsLiteral("removeHostRoute")) {
  1064     removeHostRoute(aOptions);
  1065   } else if (aOptions.mCmd.EqualsLiteral("removeHostRoutes")) {
  1066     removeHostRoutes(aOptions);
  1067   } else if (aOptions.mCmd.EqualsLiteral("addSecondaryRoute")) {
  1068     addSecondaryRoute(aOptions);
  1069   } else if (aOptions.mCmd.EqualsLiteral("removeSecondaryRoute")) {
  1070     removeSecondaryRoute(aOptions);
  1071   } else if (aOptions.mCmd.EqualsLiteral("getNetworkInterfaceStats")) {
  1072     getNetworkInterfaceStats(aOptions);
  1073   } else if (aOptions.mCmd.EqualsLiteral("setNetworkInterfaceAlarm")) {
  1074     setNetworkInterfaceAlarm(aOptions);
  1075   } else if (aOptions.mCmd.EqualsLiteral("enableNetworkInterfaceAlarm")) {
  1076     enableNetworkInterfaceAlarm(aOptions);
  1077   } else if (aOptions.mCmd.EqualsLiteral("disableNetworkInterfaceAlarm")) {
  1078     disableNetworkInterfaceAlarm(aOptions);
  1079   } else if (aOptions.mCmd.EqualsLiteral("setWifiOperationMode")) {
  1080     setWifiOperationMode(aOptions);
  1081   } else if (aOptions.mCmd.EqualsLiteral("setDhcpServer")) {
  1082     setDhcpServer(aOptions);
  1083   } else if (aOptions.mCmd.EqualsLiteral("setWifiTethering")) {
  1084     setWifiTethering(aOptions);
  1085   } else if (aOptions.mCmd.EqualsLiteral("setUSBTethering")) {
  1086     setUSBTethering(aOptions);
  1087   } else if (aOptions.mCmd.EqualsLiteral("enableUsbRndis")) {
  1088     enableUsbRndis(aOptions);
  1089   } else if (aOptions.mCmd.EqualsLiteral("updateUpStream")) {
  1090     updateUpStream(aOptions);
  1091   } else {
  1092     WARN("unknon message");
  1093     return;
  1096   if (!aOptions.mIsAsync) {
  1097     NetworkResultOptions result;
  1098     result.mRet = ret;
  1099     postMessage(aOptions, result);
  1103 /**
  1104  * Handle received data from netd.
  1105  */
  1106 void NetworkUtils::onNetdMessage(NetdCommand* aCommand)
  1108   char* data = (char*)aCommand->mData;
  1110   // get code & reason.
  1111   char* result = strtok(data, NETD_MESSAGE_DELIMIT);
  1113   if (!result) {
  1114     nextNetdCommand();
  1115     return;
  1117   uint32_t code = atoi(result);
  1119   if (!isBroadcastMessage(code) && SDK_VERSION >= 16) {
  1120     strtok(nullptr, NETD_MESSAGE_DELIMIT);
  1123   char* reason = strtok(nullptr, "\0");
  1125   if (isBroadcastMessage(code)) {
  1126     DEBUG("Receiving broadcast message from netd.");
  1127     DEBUG("          ==> Code: %d  Reason: %s", code, reason);
  1128     sendBroadcastMessage(code, reason);
  1129     nextNetdCommand();
  1130     return;
  1133    // Set pending to false before we handle next command.
  1134   DEBUG("Receiving \"%s\" command response from netd.", gCurrentCommand.command);
  1135   DEBUG("          ==> Code: %d  Reason: %s", code, reason);
  1137   gReason.AppendElement(nsCString(reason));
  1139   // 1xx response code regards as command is proceeding, we need to wait for
  1140   // final response code such as 2xx, 4xx and 5xx before sending next command.
  1141   if (isProceeding(code)) {
  1142     return;
  1145   if (isComplete(code)) {
  1146     gPending = false;
  1149   if (gCurrentCommand.callback) {
  1150     char buf[BUF_SIZE];
  1151     join(gReason, INTERFACE_DELIMIT, BUF_SIZE, buf);
  1153     NetworkResultOptions result;
  1154     result.mResultCode = code;
  1155     result.mResultReason = NS_ConvertUTF8toUTF16(buf);
  1156     (*gCurrentCommand.callback)(gCurrentCommand.chain, isError(code), result);
  1157     gReason.Clear();
  1160   // Handling pending commands if any.
  1161   if (isComplete(code)) {
  1162     nextNetdCommand();
  1166 /**
  1167  * Start/Stop DHCP server.
  1168  */
  1169 bool NetworkUtils::setDhcpServer(NetworkParams& aOptions)
  1171   if (aOptions.mEnabled) {
  1172     aOptions.mWifiStartIp = aOptions.mStartIp;
  1173     aOptions.mWifiEndIp = aOptions.mEndIp;
  1174     aOptions.mIp = aOptions.mServerIp;
  1175     aOptions.mPrefix = aOptions.mMaskLength;
  1176     aOptions.mLink = NS_ConvertUTF8toUTF16("up");
  1178     RUN_CHAIN(aOptions, sStartDhcpServerChain, setDhcpServerFail)
  1179   } else {
  1180     RUN_CHAIN(aOptions, sStopDhcpServerChain, setDhcpServerFail)
  1182   return true;
  1185 /**
  1186  * Set DNS servers for given network interface.
  1187  */
  1188 bool NetworkUtils::setDNS(NetworkParams& aOptions)
  1190   uint32_t length = aOptions.mDnses.Length();
  1192   if (length > 0) {
  1193     for (uint32_t i = 0; i < length; i++) {
  1194       NS_ConvertUTF16toUTF8 autoDns(aOptions.mDnses[i]);
  1196       char dns_prop_key[PROPERTY_VALUE_MAX];
  1197       snprintf(dns_prop_key, sizeof dns_prop_key, "net.dns%d", i+1);
  1198       property_set(dns_prop_key, autoDns.get());
  1200   } else {
  1201     // Set dnses from system properties.
  1202     IFProperties interfaceProperties;
  1203     getIFProperties(GET_CHAR(mIfname), interfaceProperties);
  1205     property_set("net.dns1", interfaceProperties.dns1);
  1206     property_set("net.dns2", interfaceProperties.dns2);
  1209   // Bump the DNS change property.
  1210   char dnschange[PROPERTY_VALUE_MAX];
  1211   property_get("net.dnschange", dnschange, "0");
  1213   char num[PROPERTY_VALUE_MAX];
  1214   snprintf(num, PROPERTY_VALUE_MAX - 1, "%d", atoi(dnschange) + 1);
  1215   property_set("net.dnschange", num);
  1217   // DNS needs to be set through netd since JellyBean (4.3).
  1218   if (SDK_VERSION >= 18) {
  1219     RUN_CHAIN(aOptions, sSetDnsChain, setDnsFail)
  1222   return true;
  1225 /**
  1226  * Set default route and DNS servers for given network interface.
  1227  */
  1228 bool NetworkUtils::setDefaultRouteAndDNS(NetworkParams& aOptions)
  1230   NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
  1232   if (!aOptions.mOldIfname.IsEmpty()) {
  1233     // Remove IPv4's default route.
  1234     mNetUtils->do_ifc_remove_default_route(GET_CHAR(mOldIfname));
  1235     // Remove IPv6's default route.
  1236     mNetUtils->do_ifc_remove_route(GET_CHAR(mOldIfname), "::", 0, NULL);
  1239   uint32_t length = aOptions.mGateways.Length();
  1240   if (length > 0) {
  1241     for (uint32_t i = 0; i < length; i++) {
  1242       NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[i]);
  1244       int type = getIpType(autoGateway.get());
  1245       if (type != AF_INET && type != AF_INET6) {
  1246         continue;
  1249       if (type == AF_INET6) {
  1250         mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, autoGateway.get());
  1251       } else { /* type == AF_INET */
  1252         mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(autoGateway.get()));
  1255   } else {
  1256     // Set default froute from system properties.
  1257     char key[PROPERTY_KEY_MAX];
  1258     char gateway[PROPERTY_KEY_MAX];
  1260     snprintf(key, sizeof key - 1, "net.%s.gw", autoIfname.get());
  1261     property_get(key, gateway, "");
  1263     int type = getIpType(gateway);
  1264     if (type != AF_INET && type != AF_INET6) {
  1265       return false;
  1268     if (type == AF_INET6) {
  1269       mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, gateway);
  1270     } else { /* type == AF_INET */
  1271       mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(gateway));
  1275   setDNS(aOptions);
  1276   return true;
  1279 /**
  1280  * Remove default route for given network interface.
  1281  */
  1282 bool NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
  1284   uint32_t length = aOptions.mGateways.Length();
  1285   for (uint32_t i = 0; i < length; i++) {
  1286     NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[i]);
  1288     int type = getIpType(autoGateway.get());
  1289     if (type != AF_INET && type != AF_INET6) {
  1290       return false;
  1293     mNetUtils->do_ifc_remove_route(GET_CHAR(mIfname),
  1294                                    type == AF_INET ? "0.0.0.0" : "::",
  1295                                    0, autoGateway.get());
  1298   return true;
  1301 /**
  1302  * Add host route for given network interface.
  1303  */
  1304 bool NetworkUtils::addHostRoute(NetworkParams& aOptions)
  1306   NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
  1307   int type, prefix;
  1309   uint32_t length = aOptions.mHostnames.Length();
  1310   for (uint32_t i = 0; i < length; i++) {
  1311     NS_ConvertUTF16toUTF8 autoHostname(aOptions.mHostnames[i]);
  1313     type = getIpType(autoHostname.get());
  1314     if (type != AF_INET && type != AF_INET6) {
  1315       continue;
  1318     uint32_t index = selectGateway(aOptions.mGateways, type);
  1319     if (index >= aOptions.mGateways.Length()) {
  1320       continue;
  1323     NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[index]);
  1324     prefix = type == AF_INET ? 32 : 128;
  1325     mNetUtils->do_ifc_add_route(autoIfname.get(), autoHostname.get(), prefix,
  1326                                 autoGateway.get());
  1328   return true;
  1331 /**
  1332  * Remove host route for given network interface.
  1333  */
  1334 bool NetworkUtils::removeHostRoute(NetworkParams& aOptions)
  1336   NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
  1337   int type, prefix;
  1339   uint32_t length = aOptions.mHostnames.Length();
  1340   for (uint32_t i = 0; i < length; i++) {
  1341     NS_ConvertUTF16toUTF8 autoHostname(aOptions.mHostnames[i]);
  1343     type = getIpType(autoHostname.get());
  1344     if (type != AF_INET && type != AF_INET6) {
  1345       continue;
  1348     uint32_t index = selectGateway(aOptions.mGateways, type);
  1349     if (index >= aOptions.mGateways.Length()) {
  1350       continue;
  1353     NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[index]);
  1354     prefix = type == AF_INET ? 32 : 128;
  1355     mNetUtils->do_ifc_remove_route(autoIfname.get(), autoHostname.get(), prefix,
  1356                                    autoGateway.get());
  1358   return true;
  1361 /**
  1362  * Remove the routes associated with the named interface.
  1363  */
  1364 bool NetworkUtils::removeHostRoutes(NetworkParams& aOptions)
  1366   mNetUtils->do_ifc_remove_host_routes(GET_CHAR(mIfname));
  1367   return true;
  1370 bool NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
  1372   NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
  1373   NS_ConvertUTF16toUTF8 autoIp(aOptions.mIp);
  1375   int type = getIpType(autoIp.get());
  1376   if (type != AF_INET && type != AF_INET6) {
  1377     return false;
  1380   uint32_t prefixLength = GET_FIELD(mPrefixLength);
  1382   if (type == AF_INET6) {
  1383     // Calculate subnet.
  1384     struct in6_addr in6;
  1385     if (inet_pton(AF_INET6, autoIp.get(), &in6) != 1) {
  1386       return false;
  1389     uint32_t p, i, p1, mask;
  1390     p = prefixLength;
  1391     i = 0;
  1392     while (i < 4) {
  1393       p1 = p > 32 ? 32 : p;
  1394       p -= p1;
  1395       mask = p1 ? ~0x0 << (32 - p1) : 0;
  1396       in6.s6_addr32[i++] &= htonl(mask);
  1399     char subnetStr[INET6_ADDRSTRLEN];
  1400     if (!inet_ntop(AF_INET6, &in6, subnetStr, sizeof subnetStr)) {
  1401       return false;
  1404     // Remove default route.
  1405     mNetUtils->do_ifc_remove_route(autoIfname.get(), "::", 0, NULL);
  1407     // Remove subnet route.
  1408     mNetUtils->do_ifc_remove_route(autoIfname.get(), subnetStr, prefixLength, NULL);
  1409     return true;
  1412   /* type == AF_INET */
  1413   uint32_t ip = inet_addr(autoIp.get());
  1414   uint32_t netmask = makeMask(prefixLength);
  1415   uint32_t subnet = ip & netmask;
  1416   const char* gateway = "0.0.0.0";
  1417   struct in_addr addr;
  1418   addr.s_addr = subnet;
  1419   const char* dst = inet_ntoa(addr);
  1421   mNetUtils->do_ifc_remove_default_route(autoIfname.get());
  1422   mNetUtils->do_ifc_remove_route(autoIfname.get(), dst, prefixLength, gateway);
  1423   return true;
  1426 bool NetworkUtils::addSecondaryRoute(NetworkParams& aOptions)
  1428   char command[MAX_COMMAND_SIZE];
  1429   snprintf(command, MAX_COMMAND_SIZE - 1,
  1430            "interface route add %s secondary %s %s %s",
  1431            GET_CHAR(mIfname),
  1432            GET_CHAR(mIp),
  1433            GET_CHAR(mPrefix),
  1434            GET_CHAR(mGateway));
  1436   doCommand(command, nullptr, nullptr);
  1437   return true;
  1440 bool NetworkUtils::removeSecondaryRoute(NetworkParams& aOptions)
  1442   char command[MAX_COMMAND_SIZE];
  1443   snprintf(command, MAX_COMMAND_SIZE - 1,
  1444            "interface route remove %s secondary %s %s %s",
  1445            GET_CHAR(mIfname),
  1446            GET_CHAR(mIp),
  1447            GET_CHAR(mPrefix),
  1448            GET_CHAR(mGateway));
  1450   doCommand(command, nullptr, nullptr);
  1451   return true;
  1454 bool NetworkUtils::getNetworkInterfaceStats(NetworkParams& aOptions)
  1456   DEBUG("getNetworkInterfaceStats: %s", GET_CHAR(mIfname));
  1457   aOptions.mRxBytes = -1;
  1458   aOptions.mTxBytes = -1;
  1460   RUN_CHAIN(aOptions, sNetworkInterfaceStatsChain, networkInterfaceStatsFail);
  1461   return  true;
  1464 bool NetworkUtils::setNetworkInterfaceAlarm(NetworkParams& aOptions)
  1466   DEBUG("setNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
  1467   RUN_CHAIN(aOptions, sNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
  1468   return true;
  1471 bool NetworkUtils::enableNetworkInterfaceAlarm(NetworkParams& aOptions)
  1473   DEBUG("enableNetworkInterfaceAlarm: %s", GET_CHAR(mIfname));
  1474   RUN_CHAIN(aOptions, sNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
  1475   return true;
  1478 bool NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions)
  1480   DEBUG("disableNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
  1481   RUN_CHAIN(aOptions, sNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
  1482   return true;
  1485 /**
  1486  * handling main thread's reload Wifi firmware request
  1487  */
  1488 bool NetworkUtils::setWifiOperationMode(NetworkParams& aOptions)
  1490   DEBUG("setWifiOperationMode: %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
  1491   RUN_CHAIN(aOptions, sWifiOperationModeChain, wifiOperationModeFail);
  1492   return true;
  1495 /**
  1496  * handling main thread's enable/disable WiFi Tethering request
  1497  */
  1498 bool NetworkUtils::setWifiTethering(NetworkParams& aOptions)
  1500   bool enable = aOptions.mEnable;
  1501   IFProperties interfaceProperties;
  1502   getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
  1504   if (strcmp(interfaceProperties.dns1, "")) {
  1505     aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
  1507   if (strcmp(interfaceProperties.dns2, "")) {
  1508     aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
  1510   dumpParams(aOptions, "WIFI");
  1512   if (enable) {
  1513     DEBUG("Starting Wifi Tethering on %s <-> %s",
  1514            GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
  1515     RUN_CHAIN(aOptions, sWifiEnableChain, wifiTetheringFail)
  1516   } else {
  1517     DEBUG("Stopping Wifi Tethering on %s <-> %s",
  1518            GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
  1519     RUN_CHAIN(aOptions, sWifiDisableChain, wifiTetheringFail)
  1521   return true;
  1524 bool NetworkUtils::setUSBTethering(NetworkParams& aOptions)
  1526   bool enable = aOptions.mEnable;
  1527   IFProperties interfaceProperties;
  1528   getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
  1530   if (strcmp(interfaceProperties.dns1, "")) {
  1531     aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
  1533   if (strcmp(interfaceProperties.dns2, "")) {
  1534     aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
  1536   dumpParams(aOptions, "USB");
  1538   if (enable) {
  1539     DEBUG("Starting USB Tethering on %s <-> %s",
  1540            GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
  1541     RUN_CHAIN(aOptions, sUSBEnableChain, usbTetheringFail)
  1542   } else {
  1543     DEBUG("Stopping USB Tethering on %s <-> %s",
  1544            GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
  1545     RUN_CHAIN(aOptions, sUSBDisableChain, usbTetheringFail)
  1547   return true;
  1550 void NetworkUtils::escapeQuote(nsCString& aString)
  1552   aString.ReplaceSubstring("\\", "\\\\");
  1553   aString.ReplaceSubstring("\"", "\\\"");
  1556 void NetworkUtils::checkUsbRndisState(NetworkParams& aOptions)
  1558   static uint32_t retry = 0;
  1560   char currentState[PROPERTY_VALUE_MAX];
  1561   property_get(SYS_USB_STATE_PROPERTY, currentState, nullptr);
  1563   nsTArray<nsCString> stateFuncs;
  1564   split(currentState, USB_CONFIG_DELIMIT, stateFuncs);
  1565   bool rndisPresent = stateFuncs.Contains(nsCString(USB_FUNCTION_RNDIS));
  1567   if (aOptions.mEnable == rndisPresent) {
  1568     NetworkResultOptions result;
  1569     result.mEnable = aOptions.mEnable;
  1570     result.mResult = true;
  1571     postMessage(aOptions, result);
  1572     retry = 0;
  1573     return;
  1575   if (retry < USB_FUNCTION_RETRY_TIMES) {
  1576     retry++;
  1577     usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
  1578     checkUsbRndisState(aOptions);
  1579     return;
  1582   NetworkResultOptions result;
  1583   result.mResult = false;
  1584   postMessage(aOptions, result);
  1585   retry = 0;
  1588 /**
  1589  * Modify usb function's property to turn on USB RNDIS function
  1590  */
  1591 bool NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
  1593   bool report = aOptions.mReport;
  1595   // For some reason, rndis doesn't play well with diag,modem,nmea.
  1596   // So when turning rndis on, we set sys.usb.config to either "rndis"
  1597   // or "rndis,adb". When turning rndis off, we go back to
  1598   // persist.sys.usb.config.
  1599   //
  1600   // On the otoro/unagi, persist.sys.usb.config should be one of:
  1601   //
  1602   //    diag,modem,nmea,mass_storage
  1603   //    diag,modem,nmea,mass_storage,adb
  1604   //
  1605   // When rndis is enabled, sys.usb.config should be one of:
  1606   //
  1607   //    rdnis
  1608   //    rndis,adb
  1609   //
  1610   // and when rndis is disabled, it should revert to persist.sys.usb.config
  1612   char currentConfig[PROPERTY_VALUE_MAX];
  1613   property_get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
  1615   nsTArray<nsCString> configFuncs;
  1616   split(currentConfig, USB_CONFIG_DELIMIT, configFuncs);
  1618   char persistConfig[PROPERTY_VALUE_MAX];
  1619   property_get(PERSIST_SYS_USB_CONFIG_PROPERTY, persistConfig, nullptr);
  1621   nsTArray<nsCString> persistFuncs;
  1622   split(persistConfig, USB_CONFIG_DELIMIT, persistFuncs);
  1624   if (aOptions.mEnable) {
  1625     configFuncs.Clear();
  1626     configFuncs.AppendElement(nsCString(USB_FUNCTION_RNDIS));
  1627     if (persistFuncs.Contains(nsCString(USB_FUNCTION_ADB))) {
  1628       configFuncs.AppendElement(nsCString(USB_FUNCTION_ADB));
  1630   } else {
  1631     // We're turning rndis off, revert back to the persist setting.
  1632     // adb will already be correct there, so we don't need to do any
  1633     // further adjustments.
  1634     configFuncs = persistFuncs;
  1637   char newConfig[PROPERTY_VALUE_MAX] = "";
  1638   property_get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
  1639   join(configFuncs, USB_CONFIG_DELIMIT, PROPERTY_VALUE_MAX, newConfig);
  1640   if (strcmp(currentConfig, newConfig)) {
  1641     property_set(SYS_USB_CONFIG_PROPERTY, newConfig);
  1644   // Trigger the timer to check usb state and report the result to NetworkManager.
  1645   if (report) {
  1646     usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
  1647     checkUsbRndisState(aOptions);
  1649   return true;
  1652 /**
  1653  * handling upstream interface change event.
  1654  */
  1655 bool NetworkUtils::updateUpStream(NetworkParams& aOptions)
  1657   RUN_CHAIN(aOptions, sUpdateUpStreamChain, updateUpStreamFail)
  1658   return true;
  1661 void NetworkUtils::sendBroadcastMessage(uint32_t code, char* reason)
  1663   NetworkResultOptions result;
  1664   switch(code) {
  1665     case NETD_COMMAND_INTERFACE_CHANGE:
  1666       result.mTopic = NS_ConvertUTF8toUTF16("netd-interface-change");
  1667       break;
  1668     case NETD_COMMAND_BANDWIDTH_CONTROLLER:
  1669       result.mTopic = NS_ConvertUTF8toUTF16("netd-bandwidth-control");
  1670       break;
  1671     default:
  1672       return;
  1675   result.mBroadcast = true;
  1676   result.mReason = NS_ConvertUTF8toUTF16(reason);
  1677   postMessage(result);
  1680 inline uint32_t NetworkUtils::netdResponseType(uint32_t code)
  1682   return (code / 100) * 100;
  1685 inline bool NetworkUtils::isBroadcastMessage(uint32_t code)
  1687   uint32_t type = netdResponseType(code);
  1688   return type == NETD_COMMAND_UNSOLICITED;
  1691 inline bool NetworkUtils::isError(uint32_t code)
  1693   uint32_t type = netdResponseType(code);
  1694   return type != NETD_COMMAND_PROCEEDING && type != NETD_COMMAND_OKAY;
  1697 inline bool NetworkUtils::isComplete(uint32_t code)
  1699   uint32_t type = netdResponseType(code);
  1700   return type != NETD_COMMAND_PROCEEDING;
  1703 inline bool NetworkUtils::isProceeding(uint32_t code)
  1705   uint32_t type = netdResponseType(code);
  1706   return type == NETD_COMMAND_PROCEEDING;
  1709 void NetworkUtils::dumpParams(NetworkParams& aOptions, const char* aType)
  1711 #ifdef _DEBUG
  1712   DEBUG("Dump params:");
  1713   DEBUG("     ifname: %s", GET_CHAR(mIfname));
  1714   DEBUG("     ip: %s", GET_CHAR(mIp));
  1715   DEBUG("     link: %s", GET_CHAR(mLink));
  1716   DEBUG("     prefix: %s", GET_CHAR(mPrefix));
  1717   DEBUG("     wifiStartIp: %s", GET_CHAR(mWifiStartIp));
  1718   DEBUG("     wifiEndIp: %s", GET_CHAR(mWifiEndIp));
  1719   DEBUG("     usbStartIp: %s", GET_CHAR(mUsbStartIp));
  1720   DEBUG("     usbEndIp: %s", GET_CHAR(mUsbEndIp));
  1721   DEBUG("     dnsserver1: %s", GET_CHAR(mDns1));
  1722   DEBUG("     dnsserver2: %s", GET_CHAR(mDns2));
  1723   DEBUG("     internalIfname: %s", GET_CHAR(mInternalIfname));
  1724   DEBUG("     externalIfname: %s", GET_CHAR(mExternalIfname));
  1725   if (!strcmp(aType, "WIFI")) {
  1726     DEBUG("     wifictrlinterfacename: %s", GET_CHAR(mWifictrlinterfacename));
  1727     DEBUG("     ssid: %s", GET_CHAR(mSsid));
  1728     DEBUG("     security: %s", GET_CHAR(mSecurity));
  1729     DEBUG("     key: %s", GET_CHAR(mKey));
  1731 #endif
  1734 #undef GET_CHAR
  1735 #undef GET_FIELD

mercurial