Bug 1000040 - Part 1: Supports Ethernet in gecko. r=vchang, r=bholley
authorJohn Shih <jshih@mozilla.com>
Mon, 19 May 2014 15:52:02 +0800
changeset 192585 f54af6237ce94f9f01c549c3edd3505e3019ba33
parent 192584 323c8a4cb90e9ef8a9cb1171a1d8bc6661184792
child 192586 78ba6f47a5a7369a2cc8eb682ded9225ea1dac1a
push id27090
push usercbook@mozilla.com
push dateMon, 07 Jul 2014 13:07:36 +0000
treeherdermozilla-central@085eea991bb9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvchang, bholley
bugs1000040
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1000040 - Part 1: Supports Ethernet in gecko. r=vchang, r=bholley
dom/system/gonk/NetworkService.js
dom/system/gonk/NetworkService.manifest
dom/system/gonk/NetworkUtils.cpp
dom/system/gonk/NetworkUtils.h
dom/system/gonk/NetworkWorker.cpp
dom/system/gonk/NetworkWorker.h
dom/system/gonk/nsINetworkService.idl
dom/webidl/NetworkOptions.webidl
--- a/dom/system/gonk/NetworkService.js
+++ b/dom/system/gonk/NetworkService.js
@@ -7,17 +7,17 @@
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 
 const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
-const NETWORKSERVICE_CID = Components.ID("{baec696c-c78d-42db-8b44-603f8fbfafb4}");
+const NETWORKSERVICE_CID = Components.ID("{48c13741-aec9-4a86-8962-432011708261}");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gNetworkWorker",
                                    "@mozilla.org/network/worker;1",
                                    "nsINetworkWorker");
 
 // 1xx - Requested action is proceeding
 const NETD_COMMAND_PROCEEDING   = 100;
 // 2xx - Requested action has been successfully completed
@@ -537,16 +537,91 @@ NetworkService.prototype = {
     this.controlMessage(params, function(data) {
       let code = data.resultCode;
       let reason = data.resultReason;
       if(DEBUG) debug("updateUpStream result: Code " + code + " reason " + reason);
       callback.updateUpStreamResult(!isError(code), data.curExternalIfname);
     });
   },
 
+  getInterfaces: function(callback) {
+    let params = {
+      cmd: "getInterfaces",
+      isAsync: true
+    };
+
+    this.controlMessage(params, function(data) {
+      if(DEBUG) debug("getInterfaces result: " + JSON.stringify(data));
+      let success = !isError(data.resultCode);
+      callback.getInterfacesResult(success, data.interfaceList);
+    });
+  },
+
+  setInterfaceConfig: function(config, callback) {
+    config.cmd = "setInterfaceConfig";
+    config.isAsync = true;
+
+    this.controlMessage(config, function(data) {
+      if(DEBUG) debug("setInterfaceConfig result: " + JSON.stringify(data));
+      let success = !isError(data.resultCode);
+      callback.setInterfaceConfigResult(success);
+    });
+  },
+
+  getInterfaceConfig: function(ifname, callback) {
+    let params = {
+      cmd: "getInterfaceConfig",
+      ifname: ifname,
+      isAsync: true
+    };
+
+    this.controlMessage(params, function(data) {
+      if(DEBUG) debug("getInterfaceConfig result: " + JSON.stringify(data));
+      let success = !isError(data.resultCode);
+      let result = { ip: data.ipAddr,
+                     prefix: data.maskLength,
+                     link: data.flag,
+                     mac: data.macAddr };
+      callback.getInterfaceConfigResult(success, result);
+    });
+  },
+
+  runDhcp: function(ifname, callback) {
+    let params = {
+      cmd: "runDhcp",
+      ifname: ifname,
+      isBlocking: true
+    };
+
+    this.controlMessage(params, function(data) {
+      if(DEBUG) debug("runDhcp result: " + JSON.stringify(data));
+      let success = data.success;
+      let result = {
+        ip: data.ipAddr,
+        gateway: data.gateway,
+        dns1: data.dns1,
+        dns2: data.dns2,
+        prefix: data.maskLength,
+        server: data.server
+      };
+
+      callback.runDhcpResult(success, result);
+    });
+  },
+
+  stopDhcp: function(ifname) {
+    let params = {
+      cmd: "stopDhcp",
+      ifname: ifname,
+      isAsync: true
+    };
+
+    this.controlMessage(params);
+  },
+
   shutdown: false,
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "xpcom-shutdown":
         debug("NetworkService shutdown");
         this.shutdown = true;
         Services.obs.removeObserver(this, "xpcom-shutdown");
--- a/dom/system/gonk/NetworkService.manifest
+++ b/dom/system/gonk/NetworkService.manifest
@@ -1,3 +1,3 @@
 # NetworkService.js
-component {baec696c-c78d-42db-8b44-603f8fbfafb4} NetworkService.js
-contract @mozilla.org/network/service;1 {baec696c-c78d-42db-8b44-603f8fbfafb4}
+component {48c13741-aec9-4a86-8962-432011708261} NetworkService.js
+contract @mozilla.org/network/service;1 {48c13741-aec9-4a86-8962-432011708261}
--- a/dom/system/gonk/NetworkUtils.cpp
+++ b/dom/system/gonk/NetworkUtils.cpp
@@ -106,17 +106,17 @@ static NetworkParams *gWifiTetheringParm
 
 
 CommandFunc NetworkUtils::sWifiEnableChain[] = {
   NetworkUtils::clearWifiTetherParms,
   NetworkUtils::wifiFirmwareReload,
   NetworkUtils::startAccessPointDriver,
   NetworkUtils::setAccessPoint,
   NetworkUtils::startSoftAP,
-  NetworkUtils::setInterfaceUp,
+  NetworkUtils::setConfig,
   NetworkUtils::tetherInterface,
   NetworkUtils::setIpForwardingEnabled,
   NetworkUtils::tetheringStatus,
   NetworkUtils::startTethering,
   NetworkUtils::setDnsForwarders,
   NetworkUtils::enableNat,
   NetworkUtils::wifiTetheringSuccess
 };
@@ -147,33 +147,33 @@ CommandFunc NetworkUtils::sWifiRetryChai
   NetworkUtils::stopSoftAP,
   NetworkUtils::stopTethering,
 
   // sWifiEnableChain:
   NetworkUtils::wifiFirmwareReload,
   NetworkUtils::startAccessPointDriver,
   NetworkUtils::setAccessPoint,
   NetworkUtils::startSoftAP,
-  NetworkUtils::setInterfaceUp,
+  NetworkUtils::setConfig,
   NetworkUtils::tetherInterface,
   NetworkUtils::setIpForwardingEnabled,
   NetworkUtils::tetheringStatus,
   NetworkUtils::startTethering,
   NetworkUtils::setDnsForwarders,
   NetworkUtils::enableNat,
   NetworkUtils::wifiTetheringSuccess
 };
 
 CommandFunc NetworkUtils::sWifiOperationModeChain[] = {
   NetworkUtils::wifiFirmwareReload,
   NetworkUtils::wifiOperationModeSuccess
 };
 
 CommandFunc NetworkUtils::sUSBEnableChain[] = {
-  NetworkUtils::setInterfaceUp,
+  NetworkUtils::setConfig,
   NetworkUtils::enableNat,
   NetworkUtils::setIpForwardingEnabled,
   NetworkUtils::tetherInterface,
   NetworkUtils::tetheringStatus,
   NetworkUtils::startTethering,
   NetworkUtils::setDnsForwarders,
   NetworkUtils::usbTetheringSuccess
 };
@@ -196,17 +196,17 @@ CommandFunc NetworkUtils::sUSBFailChain[
 
 CommandFunc NetworkUtils::sUpdateUpStreamChain[] = {
   NetworkUtils::cleanUpStream,
   NetworkUtils::createUpStream,
   NetworkUtils::updateUpStreamSuccess
 };
 
 CommandFunc NetworkUtils::sStartDhcpServerChain[] = {
-  NetworkUtils::setInterfaceUp,
+  NetworkUtils::setConfig,
   NetworkUtils::startTethering,
   NetworkUtils::setDhcpServerSuccess
 };
 
 CommandFunc NetworkUtils::sStopDhcpServerChain[] = {
   NetworkUtils::stopTethering,
   NetworkUtils::setDhcpServerSuccess
 };
@@ -235,16 +235,31 @@ CommandFunc NetworkUtils::sNetworkInterf
   NetworkUtils::networkInterfaceAlarmSuccess
 };
 
 CommandFunc NetworkUtils::sSetDnsChain[] = {
   NetworkUtils::setDefaultInterface,
   NetworkUtils::setInterfaceDns
 };
 
+CommandFunc NetworkUtils::sGetInterfacesChain[] = {
+  NetworkUtils::getInterfaceList,
+  NetworkUtils::getInterfacesSuccess
+};
+
+CommandFunc NetworkUtils::sSetInterfaceConfigChain[] = {
+  NetworkUtils::setConfig,
+  NetworkUtils::setInterfaceConfigSuccess
+};
+
+CommandFunc NetworkUtils::sGetInterfaceConfigChain[] = {
+  NetworkUtils::getConfig,
+  NetworkUtils::getInterfaceConfigSuccess
+};
+
 /**
  * Helper function to get the mask from given prefix length.
  */
 static uint32_t makeMask(const uint32_t prefixLength)
 {
   uint32_t mask = 0;
   for (uint32_t i = 0; i < prefixLength; ++i) {
     mask |= (0x80000000 >> i);
@@ -317,16 +332,25 @@ static void join(nsTArray<nsCString>& ar
       CHECK_LENGTH(len, strlen(array[i].get()), maxlen)
       strcat(result, array[i].get());
     }
   }
 
 #undef CHECK_LEN
 }
 
+static void convertUTF8toUTF16(nsTArray<nsCString>& narrow,
+                               nsTArray<nsString>& wide,
+                               uint32_t length)
+{
+  for (uint32_t i = 0; i < length; i++) {
+    wide.AppendElement(NS_ConvertUTF8toUTF16(narrow[i].get()));
+  }
+}
+
 /**
  * Helper function to get network interface properties from the system property table.
  */
 static void getIFProperties(const char* ifname, IFProperties& prop)
 {
   char key[PROPERTY_KEY_MAX];
   snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.gw", ifname);
   property_get(key, prop.gateway, "");
@@ -681,19 +705,19 @@ void NetworkUtils::setAlarm(CommandChain
                             NetworkResultOptions& aResult)
 {
   char command[MAX_COMMAND_SIZE];
   snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setinterfacealert %s %ld", GET_CHAR(mIfname), GET_FIELD(mThreshold));
 
   doCommand(command, aChain, aCallback);
 }
 
-void NetworkUtils::setInterfaceUp(CommandChain* aChain,
-                                  CommandCallback aCallback,
-                                  NetworkResultOptions& aResult)
+void NetworkUtils::setConfig(CommandChain* aChain,
+                             CommandCallback aCallback,
+                             NetworkResultOptions& aResult)
 {
   char command[MAX_COMMAND_SIZE];
   if (SDK_VERSION >= 16) {
     snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s %s",
                      GET_CHAR(mIfname),
                      GET_CHAR(mIp),
                      GET_CHAR(mPrefix),
                      GET_CHAR(mLink));
@@ -918,16 +942,36 @@ void NetworkUtils::setInterfaceDns(Comma
     }
 
     written += ret;
   }
 
   doCommand(command, aChain, aCallback);
 }
 
+void NetworkUtils::getInterfaceList(CommandChain* aChain,
+                                    CommandCallback aCallback,
+                                    NetworkResultOptions& aResult)
+{
+  char command[MAX_COMMAND_SIZE];
+  snprintf(command, MAX_COMMAND_SIZE - 1, "interface list");
+
+  doCommand(command, aChain, aCallback);
+}
+
+void NetworkUtils::getConfig(CommandChain* aChain,
+                             CommandCallback aCallback,
+                             NetworkResultOptions& aResult)
+{
+  char command[MAX_COMMAND_SIZE];
+  snprintf(command, MAX_COMMAND_SIZE - 1, "interface getcfg %s", GET_CHAR(mIfname));
+
+  doCommand(command, aChain, aCallback);
+}
+
 #undef GET_CHAR
 #undef GET_FIELD
 
 /*
  * Netd command success/fail function
  */
 #define ASSIGN_FIELD(prop)  aResult.prop = aChain->getParams().prop;
 #define ASSIGN_FIELD_VALUE(prop, value)  aResult.prop = value;
@@ -1058,16 +1102,85 @@ void NetworkUtils::wifiOperationModeSucc
   postMessage(aChain->getParams(), aResult);
 }
 
 void NetworkUtils::setDnsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
 {
   postMessage(aOptions, aResult);
 }
 
+void NetworkUtils::getInterfacesFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
+{
+  postMessage(aOptions, aResult);
+}
+
+void NetworkUtils::getInterfacesSuccess(CommandChain* aChain,
+                                        CommandCallback aCallback,
+                                        NetworkResultOptions& aResult)
+{
+  char buf[BUF_SIZE];
+  NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
+  memcpy(buf, reason.get(), strlen(reason.get()));
+
+  nsTArray<nsCString> result;
+  split(buf, INTERFACE_DELIMIT, result);
+
+  nsTArray<nsString> interfaceList;
+  uint32_t length = result.Length();
+  convertUTF8toUTF16(result, interfaceList, length);
+
+  aResult.mInterfaceList.Construct();
+  for (uint32_t i = 0; i < length; i++) {
+    aResult.mInterfaceList.Value().AppendElement(interfaceList[i]);
+  }
+
+  postMessage(aChain->getParams(), aResult);
+}
+
+void NetworkUtils::setInterfaceConfigFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
+{
+  postMessage(aOptions, aResult);
+}
+
+void NetworkUtils::setInterfaceConfigSuccess(CommandChain* aChain,
+                                             CommandCallback aCallback,
+                                             NetworkResultOptions& aResult)
+{
+  postMessage(aChain->getParams(), aResult);
+}
+
+void NetworkUtils::getInterfaceConfigFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
+{
+  postMessage(aOptions, aResult);
+}
+
+void NetworkUtils::getInterfaceConfigSuccess(CommandChain* aChain,
+                                             CommandCallback aCallback,
+                                             NetworkResultOptions& aResult)
+{
+  char buf[BUF_SIZE];
+  NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
+  memcpy(buf, reason.get(), strlen(reason.get()));
+
+  nsTArray<nsCString> result;
+  split(buf, NETD_MESSAGE_DELIMIT, result);
+
+  ASSIGN_FIELD_VALUE(mMacAddr, NS_ConvertUTF8toUTF16(result[0]))
+  ASSIGN_FIELD_VALUE(mIpAddr, NS_ConvertUTF8toUTF16(result[1]))
+  ASSIGN_FIELD_VALUE(mMaskLength, atof(result[2].get()))
+
+  if (result[3].Find("up")) {
+    ASSIGN_FIELD_VALUE(mFlag, NS_ConvertUTF8toUTF16("up"))
+  } else {
+    ASSIGN_FIELD_VALUE(mFlag, NS_ConvertUTF8toUTF16("down"))
+  }
+
+  postMessage(aChain->getParams(), aResult);
+}
+
 #undef ASSIGN_FIELD
 #undef ASSIGN_FIELD_VALUE
 
 NetworkUtils::NetworkUtils(MessageCallback aCallback)
  : mMessageCallback(aCallback)
 {
   mNetUtils = new NetUtils();
 
@@ -1122,16 +1235,24 @@ void NetworkUtils::ExecuteCommand(Networ
   } else if (aOptions.mCmd.EqualsLiteral("setWifiTethering")) {
     setWifiTethering(aOptions);
   } else if (aOptions.mCmd.EqualsLiteral("setUSBTethering")) {
     setUSBTethering(aOptions);
   } else if (aOptions.mCmd.EqualsLiteral("enableUsbRndis")) {
     enableUsbRndis(aOptions);
   } else if (aOptions.mCmd.EqualsLiteral("updateUpStream")) {
     updateUpStream(aOptions);
+  } else if (aOptions.mCmd.EqualsLiteral("getInterfaces")) {
+    getInterfaces(aOptions);
+  } else if (aOptions.mCmd.EqualsLiteral("stopDhcp")) {
+    stopDhcp(aOptions);
+  } else if (aOptions.mCmd.EqualsLiteral("setInterfaceConfig")) {
+    setInterfaceConfig(aOptions);
+  } else if (aOptions.mCmd.EqualsLiteral("getInterfaceConfig")) {
+    getInterfaceConfig(aOptions);
   } else {
     WARN("unknon message");
     return;
   }
 
   if (!aOptions.mIsAsync) {
     NetworkResultOptions result;
     result.mRet = ret;
@@ -1711,24 +1832,60 @@ bool NetworkUtils::enableUsbRndis(Networ
   if (report) {
     usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
     checkUsbRndisState(aOptions);
   }
   return true;
 }
 
 /**
- * handling upstream interface change event.
+ * Handling upstream interface change event.
  */
 bool NetworkUtils::updateUpStream(NetworkParams& aOptions)
 {
   RUN_CHAIN(aOptions, sUpdateUpStreamChain, updateUpStreamFail)
   return true;
 }
 
+/**
+ * Stop dhcp client deamon.
+ */
+bool NetworkUtils::stopDhcp(NetworkParams& aOptions)
+{
+  mNetUtils->do_dhcp_stop(GET_CHAR(mIfname));
+  return true;
+}
+
+/**
+ * Get existing network interfaces.
+ */
+bool NetworkUtils::getInterfaces(NetworkParams& aOptions)
+{
+  RUN_CHAIN(aOptions, sGetInterfacesChain, getInterfacesFail)
+  return true;
+}
+
+/**
+ * Set network config for a specified interface.
+ */
+bool NetworkUtils::setInterfaceConfig(NetworkParams& aOptions)
+{
+  RUN_CHAIN(aOptions, sSetInterfaceConfigChain, setInterfaceConfigFail)
+  return true;
+}
+
+/**
+ * Get network config of a specified interface.
+ */
+bool NetworkUtils::getInterfaceConfig(NetworkParams& aOptions)
+{
+  RUN_CHAIN(aOptions, sGetInterfaceConfigChain, getInterfaceConfigFail)
+  return true;
+}
+
 void NetworkUtils::sendBroadcastMessage(uint32_t code, char* reason)
 {
   NetworkResultOptions result;
   switch(code) {
     case NETD_COMMAND_INTERFACE_CHANGE:
       result.mTopic = NS_ConvertUTF8toUTF16("netd-interface-change");
       break;
     case NETD_COMMAND_BANDWIDTH_CONTROLLER:
--- a/dom/system/gonk/NetworkUtils.h
+++ b/dom/system/gonk/NetworkUtils.h
@@ -67,16 +67,17 @@ public:
     mEndIp = aOther.mEndIp;
     mServerIp = aOther.mServerIp;
     mMaskLength = aOther.mMaskLength;
     mPreInternalIfname = aOther.mPreInternalIfname;
     mPreExternalIfname = aOther.mPreExternalIfname;
     mCurInternalIfname = aOther.mCurInternalIfname;
     mCurExternalIfname = aOther.mCurExternalIfname;
     mThreshold = aOther.mThreshold;
+    mIsBlocking = aOther.mIsBlocking;
   }
 
   NetworkParams(const mozilla::dom::NetworkCommandOptions& aOther) {
 
 #define COPY_SEQUENCE_FIELD(prop, type)                                                      \
     if (aOther.prop.WasPassed()) {                                                           \
       mozilla::dom::Sequence<type > const & currentValue = aOther.prop.InternalValue();      \
       uint32_t length = currentValue.Length();                                               \
@@ -143,16 +144,17 @@ public:
     COPY_OPT_STRING_FIELD(mEndIp, EmptyString())
     COPY_OPT_STRING_FIELD(mServerIp, EmptyString())
     COPY_OPT_STRING_FIELD(mMaskLength, EmptyString())
     COPY_OPT_STRING_FIELD(mPreInternalIfname, EmptyString())
     COPY_OPT_STRING_FIELD(mPreExternalIfname, EmptyString())
     COPY_OPT_STRING_FIELD(mCurInternalIfname, EmptyString())
     COPY_OPT_STRING_FIELD(mCurExternalIfname, EmptyString())
     COPY_OPT_FIELD(mThreshold, -1)
+    COPY_OPT_FIELD(mIsBlocking, false)
 
 #undef COPY_SEQUENCE_FIELD
 #undef COPY_OPT_STRING_FIELD
 #undef COPY_OPT_FIELD
 #undef COPY_FIELD
   }
 
   int32_t mId;
@@ -193,16 +195,17 @@ public:
   nsString mEndIp;
   nsString mServerIp;
   nsString mMaskLength;
   nsString mPreInternalIfname;
   nsString mPreExternalIfname;
   nsString mCurInternalIfname;
   nsString mCurExternalIfname;
   long mThreshold;
+  bool mIsBlocking;
 };
 
 // CommandChain store the necessary information to execute command one by one.
 // Including :
 // 1. Command parameters.
 // 2. Command list.
 // 3. Error callback function.
 // 4. Index of current execution command.
@@ -276,16 +279,20 @@ private:
   bool enableNetworkInterfaceAlarm(NetworkParams& aOptions);
   bool disableNetworkInterfaceAlarm(NetworkParams& aOptions);
   bool setWifiOperationMode(NetworkParams& aOptions);
   bool setDhcpServer(NetworkParams& aOptions);
   bool setWifiTethering(NetworkParams& aOptions);
   bool setUSBTethering(NetworkParams& aOptions);
   bool enableUsbRndis(NetworkParams& aOptions);
   bool updateUpStream(NetworkParams& aOptions);
+  bool getInterfaces(NetworkParams& aOptions);
+  bool stopDhcp(NetworkParams& aOptions);
+  bool setInterfaceConfig(NetworkParams& aOptions);
+  bool getInterfaceConfig(NetworkParams& aOptions);
 
   /**
    * function pointer array holds all netd commands should be executed
    * in sequence to accomplish a given command by other module.
    */
   static CommandFunc sWifiEnableChain[];
   static CommandFunc sWifiDisableChain[];
   static CommandFunc sWifiFailChain[];
@@ -297,16 +304,19 @@ private:
   static CommandFunc sUpdateUpStreamChain[];
   static CommandFunc sStartDhcpServerChain[];
   static CommandFunc sStopDhcpServerChain[];
   static CommandFunc sNetworkInterfaceStatsChain[];
   static CommandFunc sNetworkInterfaceEnableAlarmChain[];
   static CommandFunc sNetworkInterfaceDisableAlarmChain[];
   static CommandFunc sNetworkInterfaceSetAlarmChain[];
   static CommandFunc sSetDnsChain[];
+  static CommandFunc sGetInterfacesChain[];
+  static CommandFunc sSetInterfaceConfigChain[];
+  static CommandFunc sGetInterfaceConfigChain[];
 
   /**
    * Individual netd command stored in command chain.
    */
 #define PARAMS CommandChain* aChain, CommandCallback aCallback, \
                mozilla::dom::NetworkResultOptions& aResult
   static void wifiFirmwareReload(PARAMS);
   static void startAccessPointDriver(PARAMS);
@@ -333,38 +343,47 @@ private:
   static void stopTethering(PARAMS);
   static void startTethering(PARAMS);
   static void untetherInterface(PARAMS);
   static void setDnsForwarders(PARAMS);
   static void enableNat(PARAMS);
   static void disableNat(PARAMS);
   static void setDefaultInterface(PARAMS);
   static void setInterfaceDns(PARAMS);
+  static void getInterfaceList(PARAMS);
+  static void setConfig(PARAMS);
+  static void getConfig(PARAMS);
   static void wifiTetheringSuccess(PARAMS);
   static void usbTetheringSuccess(PARAMS);
   static void networkInterfaceStatsSuccess(PARAMS);
   static void networkInterfaceAlarmSuccess(PARAMS);
   static void updateUpStreamSuccess(PARAMS);
   static void setDhcpServerSuccess(PARAMS);
   static void wifiOperationModeSuccess(PARAMS);
+  static void getInterfacesSuccess(PARAMS);
+  static void setInterfaceConfigSuccess(PARAMS);
+  static void getInterfaceConfigSuccess(PARAMS);
 #undef PARAMS
 
   /**
    * Error callback function executed when a command is fail.
    */
 #define PARAMS NetworkParams& aOptions, \
                mozilla::dom::NetworkResultOptions& aResult
   static void wifiTetheringFail(PARAMS);
   static void wifiOperationModeFail(PARAMS);
   static void usbTetheringFail(PARAMS);
   static void updateUpStreamFail(PARAMS);
   static void setDhcpServerFail(PARAMS);
   static void networkInterfaceStatsFail(PARAMS);
   static void networkInterfaceAlarmFail(PARAMS);
   static void setDnsFail(PARAMS);
+  static void getInterfacesFail(PARAMS);
+  static void setInterfaceConfigFail(PARAMS);
+  static void getInterfaceConfigFail(PARAMS);
 #undef PARAMS
 
   /**
    * Command chain processing functions.
    */
   static void next(CommandChain* aChain, bool aError,
                    mozilla::dom::NetworkResultOptions& aResult);
   static void nextNetdCommand();
--- a/dom/system/gonk/NetworkWorker.cpp
+++ b/dom/system/gonk/NetworkWorker.cpp
@@ -13,16 +13,18 @@
 
 #define NS_NETWORKWORKER_CID \
   { 0x6df093e1, 0x8127, 0x4fa7, {0x90, 0x13, 0xa3, 0xaa, 0xa7, 0x79, 0xbb, 0xdd} }
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
+#define PROPERTY_VALUE_MAX 80
+
 namespace mozilla {
 
 nsCOMPtr<nsIThread> gWorkerThread;
 
 // The singleton network worker, to be used on the main thread.
 StaticRefPtr<NetworkWorker> gNetworkWorker;
 
 // The singleton networkutils class, that can be used on any thread.
@@ -32,32 +34,51 @@ static nsAutoPtr<NetworkUtils> gNetworkU
 class NetworkResultDispatcher : public nsRunnable
 {
 public:
   NetworkResultDispatcher(const NetworkResultOptions& aResult)
   {
     MOZ_ASSERT(!NS_IsMainThread());
 
 #define COPY_FIELD(prop) mResult.prop = aResult.prop;
+#define COPY_SEQUENCE_FIELD(prop, type)                                                   \
+    if (aResult.prop.WasPassed()) {                                                       \
+      mozilla::dom::Sequence<type > const & currentValue = aResult.prop.InternalValue();  \
+      uint32_t length = currentValue.Length();                                            \
+      mResult.prop.Construct();                                                           \
+      for (uint32_t idx = 0; idx < length; idx++) {                                       \
+        mResult.prop.Value().AppendElement(currentValue[idx]);                            \
+      }                                                                                   \
+    }
     COPY_FIELD(mId)
     COPY_FIELD(mRet)
     COPY_FIELD(mBroadcast)
     COPY_FIELD(mTopic)
     COPY_FIELD(mReason)
     COPY_FIELD(mResultCode)
     COPY_FIELD(mResultReason)
     COPY_FIELD(mError)
     COPY_FIELD(mRxBytes)
     COPY_FIELD(mTxBytes)
     COPY_FIELD(mDate)
     COPY_FIELD(mEnable)
     COPY_FIELD(mResult)
     COPY_FIELD(mSuccess)
     COPY_FIELD(mCurExternalIfname)
     COPY_FIELD(mCurInternalIfname)
+    COPY_FIELD(mIpAddr)
+    COPY_FIELD(mGateway)
+    COPY_FIELD(mDns1)
+    COPY_FIELD(mDns2)
+    COPY_FIELD(mServer)
+    COPY_FIELD(mLease)
+    COPY_FIELD(mVendorInfo)
+    COPY_FIELD(mMaskLength)
+    COPY_FIELD(mFlag)
+    COPY_SEQUENCE_FIELD(mInterfaceList, nsString)
 #undef COPY_FIELD
   }
 
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (gNetworkWorker) {
@@ -87,16 +108,76 @@ public:
       gNetworkUtils->ExecuteCommand(mParams);
     }
     return NS_OK;
   }
 private:
   NetworkParams mParams;
 };
 
+// Runnable used for blocking command.
+class RunDhcpEvent : public nsRunnable
+{
+public:
+  RunDhcpEvent(const NetworkParams& aParams)
+  : mParams(aParams)
+  {}
+
+  NS_IMETHOD Run()
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+
+    nsAutoPtr<NetUtils> netUtils;
+    netUtils = new NetUtils();
+
+    NetworkResultOptions result;
+    result.mId = mParams.mId;
+
+    int32_t status;
+    char ipaddr[PROPERTY_VALUE_MAX];
+    char gateway[PROPERTY_VALUE_MAX];
+    uint32_t prefixLength;
+    char dns1[PROPERTY_VALUE_MAX];
+    char dns2[PROPERTY_VALUE_MAX];
+    char server[PROPERTY_VALUE_MAX];
+    uint32_t lease;
+    char vendorinfo[PROPERTY_VALUE_MAX];
+    status = netUtils->do_dhcp_do_request(NS_ConvertUTF16toUTF8(mParams.mIfname).get(),
+                                          ipaddr,
+                                          gateway,
+                                          &prefixLength,
+                                          dns1,
+                                          dns2,
+                                          server,
+                                          &lease,
+                                          vendorinfo);
+
+
+    if (status == 0) {
+      // run dhcp success.
+      result.mSuccess = true;
+      result.mIpAddr = NS_ConvertUTF8toUTF16(ipaddr);
+      result.mGateway = NS_ConvertUTF8toUTF16(gateway);
+      result.mDns1 = NS_ConvertUTF8toUTF16(dns1);
+      result.mDns2 = NS_ConvertUTF8toUTF16(dns2);
+      result.mServer = NS_ConvertUTF8toUTF16(server);
+      result.mLease = lease;
+      result.mVendorInfo = NS_ConvertUTF8toUTF16(vendorinfo);
+      result.mMaskLength = prefixLength;
+    }
+
+    nsCOMPtr<nsIRunnable> runnable = new NetworkResultDispatcher(result);
+    NS_DispatchToMainThread(runnable);
+
+    return NS_OK;
+  }
+private:
+  NetworkParams mParams;
+};
+
 // Runnable used dispatch netd result on the worker thread.
 class NetdEventRunnable : public nsRunnable
 {
 public:
   NetdEventRunnable(NetdCommand* aCommand)
     : mCommand(aCommand)
   {
     MOZ_ASSERT(!NS_IsMainThread());
@@ -219,26 +300,50 @@ NetworkWorker::PostMessage(JS::Handle<JS
   MOZ_ASSERT(NS_IsMainThread());
 
   NetworkCommandOptions options;
   if (!options.Init(aCx, aOptions)) {
     NS_WARNING("Bad dictionary passed to NetworkWorker::SendCommand");
     return NS_ERROR_FAILURE;
   }
 
+  NetworkParams NetworkParams(options);
+
+  if (NetworkParams.mIsBlocking) {
+    NetworkWorker::HandleBlockingCommand(NetworkParams);
+    return NS_OK;
+  }
+
   // Dispatch the command to the control thread.
-  NetworkParams NetworkParams(options);
   nsCOMPtr<nsIRunnable> runnable = new NetworkCommandDispatcher(NetworkParams);
   if (gWorkerThread) {
     gWorkerThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
   }
   return NS_OK;
 }
 
 void
+NetworkWorker::HandleBlockingCommand(NetworkParams& aOptions)
+{
+  if (aOptions.mCmd.EqualsLiteral("runDhcp")) {
+    NetworkWorker::RunDhcp(aOptions);
+  }
+}
+
+void
+NetworkWorker::RunDhcp(NetworkParams& aOptions)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIRunnable> runnable = new RunDhcpEvent(aOptions);
+  nsCOMPtr<nsIThread> thread;
+  NS_NewThread(getter_AddRefs(thread), runnable);
+}
+
+void
 NetworkWorker::DispatchNetworkResult(const NetworkResultOptions& aOptions)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mozilla::AutoSafeJSContext cx;
   JS::RootedValue val(cx);
 
   if (!ToJSValue(cx, aOptions, &val)) {
--- a/dom/system/gonk/NetworkWorker.h
+++ b/dom/system/gonk/NetworkWorker.h
@@ -6,16 +6,18 @@
 #define NetworkWorker_h
 
 #include "mozilla/dom/NetworkOptionsBinding.h"
 #include "mozilla/ipc/Netd.h"
 #include "nsINetworkWorker.h"
 #include "nsCOMPtr.h"
 #include "nsThread.h"
 
+class NetworkParams;
+
 namespace mozilla {
 
 class NetworkWorker MOZ_FINAL : public nsINetworkWorker
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSINETWORKWORKER
 
@@ -24,14 +26,17 @@ public:
   void DispatchNetworkResult(const mozilla::dom::NetworkResultOptions& aOptions);
 
 private:
   NetworkWorker();
   ~NetworkWorker();
 
   static void NotifyResult(mozilla::dom::NetworkResultOptions& aResult);
 
+  void HandleBlockingCommand(NetworkParams& aParams);
+  void RunDhcp(NetworkParams& aParams);
+
   nsCOMPtr<nsINetworkEventListener> mListener;
 };
 
 } // namespace mozilla
 
 #endif  // NetworkWorker_h
--- a/dom/system/gonk/nsINetworkService.idl
+++ b/dom/system/gonk/nsINetworkService.idl
@@ -96,20 +96,75 @@ interface nsIUpdateUpStreamCallback : ns
    * @param success
    *        Boolean to indicate the operation is successful or not.
    * @param externalIfname
    *        The external interface name.
    */
   void updateUpStreamResult(in boolean success, in DOMString externalIfname);
 };
 
+[scriptable, function, uuid(4a9166f3-7e4f-4d10-bb5c-b49ee21d6184)]
+interface nsIRunDhcpCallback : nsISupports
+{
+  /**
+   * Callback function used to report the result of dhcp request.
+   *
+   * @param success
+   *        Boolean to indicate the operation is successful or not.
+   */
+  void runDhcpResult(in boolean success, in jsval result);
+};
+
+[scriptable, function, uuid(88e3ee22-f1b3-4fa0-8a5d-793fb827c42c)]
+interface nsIGetInterfacesCallback : nsISupports
+{
+  /**
+   * Callback function used to return the list of existing network interfaces.
+   *
+   * @param success
+   *        Boolean to indicate the operation is successful or not.
+   * @param interfaceList
+   *        An array of interface name.
+   */
+  void getInterfacesResult(in boolean success, in jsval interfaceList);
+};
+
+[scriptable, function, uuid(064e02a3-d2c0-42c5-a293-1efa84056100)]
+interface nsIGetInterfaceConfigCallback : nsISupports
+{
+  /**
+   * Callback function used to return the network config of a given interface.
+   *
+   * @param success
+   *        Boolean to indicate the operation is successful or not.
+   * @param result
+   *        .ip: Ip address.
+   *        .prefix: mask length.
+   *        .link: network link properties.
+   *        .mac: mac address.
+   */
+  void getInterfaceConfigResult(in boolean success, in jsval result);
+};
+
+[scriptable, function, uuid(b370f360-6ba8-4517-a4f9-31e8f004ee91)]
+interface nsISetInterfaceConfigCallback : nsISupports
+{
+  /**
+   * Callback function used to set network cofig for a specified interface.
+   *
+   * @param success
+   *        Boolean to indicate the operation is successful or not.
+   */
+  void setInterfaceConfigResult(in boolean success);
+};
+
 /**
  * Provide network services.
  */
-[scriptable, uuid(f96461fa-e844-45d2-a6c3-8cd23ab0916b)]
+[scriptable, uuid(48c13741-aec9-4a86-8962-432011708261)]
 interface nsINetworkService : nsISupports
 {
   /**
    * Enable or disable Wifi Tethering
    *
    * @param enabled
    *        Boolean that indicates whether tethering should be enabled (true) or disabled (false).
    * @param config
@@ -340,9 +395,58 @@ interface nsINetworkService : nsISupport
    * @param current
    *        The current internal and external interface.
    * @param callback
    *        Callback function to report the result.
    */
   void updateUpStream(in jsval previous,
                       in jsval current,
                       in nsIUpdateUpStreamCallback callback);
+
+  /**
+   * Run Dhcp request.
+   *
+   * @param ifname
+   *        Target interface.
+   * @param callback
+   *        Callback function to report the result.
+   */
+  void runDhcp(in DOMString ifname, in nsIRunDhcpCallback callback);
+
+  /**
+   * Stop Dhcp daemon.
+   *
+   * @param ifname
+   *        Target interface.
+   */
+  void stopDhcp(in DOMString ifname);
+
+  /*
+   * Obtain interfaces list.
+   *
+   * @param callback
+   *        Callback function to return the result.
+   */
+  void getInterfaces(in nsIGetInterfacesCallback callback);
+
+  /**
+   * Set config for a network interface.
+   *
+   * @param config
+   *        .ifname: Target interface.
+   *        .ip: Ip address.
+   *        .prefix: mask length.
+   *        .link: network link properties.
+   * @param callback
+   *        Callback function to report the result.
+   */
+  void setInterfaceConfig(in jsval config, in nsISetInterfaceConfigCallback callback);
+
+  /**
+   * Get config of a network interface.
+   *
+   * @param ifname
+   *        Target interface.
+   * @param callback
+   *        Callback function to report the result.
+   */
+  void getInterfaceConfig(in DOMString ifname, in nsIGetInterfaceConfigCallback callback);
 };
--- a/dom/webidl/NetworkOptions.webidl
+++ b/dom/webidl/NetworkOptions.webidl
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
-* This dictionnary holds the parameters sent to the network worker.
+* This dictionary holds the parameters sent to the network worker.
 */
 dictionary NetworkCommandOptions
 {
   long id = 0;                        // opaque id.
   DOMString cmd = "";                 // the command name.
   DOMString ifname;                   // for "removeNetworkRoute", "setDNS",
                                       //     "setDefaultRouteAndDNS", "removeDefaultRoute"
                                       //     "addHostRoute", "removeHostRoute"
@@ -50,16 +50,17 @@ dictionary NetworkCommandOptions
   DOMString startIp;                  // for "setDhcpServer".
   DOMString endIp;                    // for "setDhcpServer".
   DOMString serverIp;                 // for "setDhcpServer".
   DOMString maskLength;               // for "setDhcpServer".
   DOMString preInternalIfname;        // for "updateUpStream".
   DOMString preExternalIfname;        // for "updateUpStream".
   DOMString curInternalIfname;        // for "updateUpStream".
   DOMString curExternalIfname;        // for "updateUpStream".
+  boolean isBlocking;                 // for "runDhcp".
 };
 
 /**
 * This dictionary holds the parameters sent back to NetworkService.js.
 */
 dictionary NetworkResultOptions
 {
   long id = 0;                        // opaque id.
@@ -76,9 +77,23 @@ dictionary NetworkResultOptions
   float txBytes = -1;                 // for "getNetworkInterfaceStats".
   DOMString date = "";                // for "getNetworkInterfaceStats".
   boolean enable = false;             // for "setWifiTethering", "setUSBTethering"
                                       //     "enableUsbRndis".
   boolean result = false;             // for "enableUsbRndis".
   boolean success = false;            // for "setDhcpServer".
   DOMString curExternalIfname = "";   // for "updateUpStream".
   DOMString curInternalIfname = "";   // for "updateUpStream".
+
+  DOMString ipAddr = "";              // for "runDhcp", "getInterfaceConfig".
+  DOMString gateway = "";             // for "runDhcp".
+  DOMString dns1 = "";                // for "runDhcp".
+  DOMString dns2 = "";                // for "runDhcp".
+  DOMString server = "";              // for "runDhcp".
+  short lease = 0;                    // for "runDhcp".
+  DOMString vendorInfo = "";          // for "runDhcp".
+  short maskLength = 0;               // for "runDhcp".
+
+  DOMString flag = "down";            // for "getInterfaceConfig".
+  DOMString macAddr = "";             // for "getInterfaceConfig".
+
+  sequence<DOMString> interfaceList;  // for "getInterfaceList".
 };