Bug 834573 - B2G Wifi: IP and default route still exist after forget network. r=vchang
authorDimi Lee <dlee@mozilla.com>
Thu, 02 May 2013 18:02:33 +0800
changeset 131903 4dd6f2744682245af0d5d04c93de115a39d41b1b
parent 131895 630974b4fa14a09851a784f529d4e6af148e15b4
child 131904 c9377ee6a251cdaeabbf7cf68fde28587a88d2fb
push id24678
push userryanvm@gmail.com
push dateThu, 16 May 2013 01:15:09 +0000
treeherdermozilla-central@19cc1efe8097 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvchang
bugs834573
milestone24.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 834573 - B2G Wifi: IP and default route still exist after forget network. r=vchang
dom/system/gonk/NetworkManager.js
dom/system/gonk/net_worker.js
dom/system/gonk/systemlibs.js
dom/wifi/WifiWorker.js
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -254,16 +254,20 @@ NetworkManager.prototype = {
             break;
           case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
             // Remove host route for data calls
             if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
               this.removeHostRoute(network);
             }
+            // Remove routing table in /proc/net/route
+            if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+              this.resetRoutingTable(this._activeInfo);
+            }
             // Abort ongoing captive portal detection on the wifi interface
             CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, network);
             this.setAndConfigureActive();
             // Update data connection when Wifi connected/disconnected
             if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
               this.mRIL.updateRILNetworkInterface();
             }
             break;
@@ -349,16 +353,19 @@ NetworkManager.prototype = {
       throw "Invalid network type";
     }
     this._preferredNetworkType = val;
   },
 
   active: null,
   _overriddenActive: null,
 
+  // Clone network info so we can still get information when network is disconnected
+  _activeInfo: null,
+
   overrideActive: function overrideActive(network) {
     this._overriddenActive = network;
     this.setAndConfigureActive();
   },
 
   getNetworkInterfaceStats: function getNetworkInterfaceStats(connectionType, callback) {
     let iface = this.getNetworkInterface(connectionType);
 
@@ -437,24 +444,26 @@ NetworkManager.prototype = {
         this.active.type == this._preferredNetworkType) {
       debug("Active network is already our preferred type.");
       this.setDefaultRouteAndDNS(oldActive);
       return;
     }
 
     // Find a suitable network interface to activate.
     this.active = null;
+    this._activeInfo = Object.create(null);
     for each (let network in this.networkInterfaces) {
       if (network.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
         continue;
       }
       if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
         defaultDataNetwork = network;
       }
       this.active = network;
+      this._activeInfo = {name:network.name, ip:network.ip, netmask:network.netmask};
       if (network.type == this.preferredNetworkType) {
         debug("Found our preferred type of network: " + network.name);
         break;
       }
     }
     if (this.active) {
       // Give higher priority to default data APN than seconary APN.
       // If default data APN is not connected, we still set default route
@@ -471,16 +480,26 @@ NetworkManager.prototype = {
       }
     }
 
     if (this._manageOfflineStatus) {
       Services.io.offline = !this.active;
     }
   },
 
+  resetRoutingTable: function resetRoutingTable(network) {
+    let options = {
+      cmd: "removeNetworkRoute",
+      ifname: network.name,
+      ip : network.ip,
+      netmask: network.netmask,
+    };
+    this.worker.postMessage(options);
+  },
+
   setDefaultRouteAndDNS: function setDefaultRouteAndDNS(oldInterface) {
     debug("Going to change route and DNS to " + this.active.name);
     let options = {
       cmd: this.active.dhcp ? "runDHCPAndSetDefaultRouteAndDNS" : "setDefaultRouteAndDNS",
       ifname: this.active.name,
       oldIfname: (oldInterface && oldInterface != this.active) ? oldInterface.name : null,
       gateway_str: this.active.gateway,
       dns1_str: this.active.dns1,
--- a/dom/system/gonk/net_worker.js
+++ b/dom/system/gonk/net_worker.js
@@ -240,16 +240,28 @@ function addHostRoute(options) {
  */
 function removeHostRoute(options) {
   libnetutils.ifc_remove_route(options.ifname, options.dns1, 32, options.gateway);
   libnetutils.ifc_remove_route(options.ifname, options.dns2, 32, options.gateway);
   libnetutils.ifc_remove_route(options.ifname, options.httpproxy, 32, options.gateway);
   libnetutils.ifc_remove_route(options.ifname, options.mmsproxy, 32, options.gateway);
 }
 
+function removeNetworkRoute(options) {
+  let ipvalue = netHelpers.stringToIP(options.ip);
+  let netmaskvalue = netHelpers.stringToIP(options.netmask);
+  let subnet = netmaskvalue & ipvalue;
+  let dst = netHelpers.ipToString(subnet);
+  let prefixLength = netHelpers.getMaskLength(netmaskvalue);
+  let gateway = "0.0.0.0";
+
+  libnetutils.ifc_remove_default_route(options.ifname);
+  libnetutils.ifc_remove_route(options.ifname, dst, prefixLength, gateway);
+}
+
 let gCommandQueue = [];
 let gCurrentCommand = null;
 let gCurrentCallback = null;
 let gPending = false;
 
 /**
  * Handle received data from netd.
  */
--- a/dom/system/gonk/systemlibs.js
+++ b/dom/system/gonk/systemlibs.js
@@ -399,10 +399,23 @@ this.netHelpers = {
    * Make a subnet mask.
    */
   makeMask: function makeMask(len) {
     let mask = 0;
     for (let i = 0; i < len; ++i) {
       mask |= (0x80000000 >> i);
     }
     return this.ntohl(mask);
+  },
+
+  /**
+   * Get Mask length from given mask address
+   */
+  getMaskLength: function getMaskLength(mask) {
+    let len = 0;
+    let netmask = this.ntohl(mask);
+    while (netmask & 0x80000000) {
+        len++;
+        netmask = netmask << 1;
+    }
+    return len;
   }
 };
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -742,16 +742,20 @@ var WifiManager = (function() {
       return;
     }
 
     retryTimer = null;
     notify("supplicantlost", { success: false });
   }
 
   manager.connectionDropped = function(callback) {
+    // Reset network interface when connection drop
+    configureInterface(manager.ifname, 0, 0, 0, 0, 0, function (data) {
+    });
+
     // If we got disconnected, kill the DHCP client in preparation for
     // reconnection.
     resetConnections(manager.ifname, function() {
       stopDhcp(manager.ifname, function() {
         callback();
       });
     });
   }