Merge "Replace custom logwrapper implementation with liblogwrap"
diff --git a/Android.mk b/Android.mk
index 787e491..a8a6bb2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -4,6 +4,7 @@
 
 LOCAL_SRC_FILES:=                                      \
                   BandwidthController.cpp              \
+                  ClatdController.cpp                  \
                   CommandListener.cpp                  \
                   DnsProxyListener.cpp                 \
                   FirewallController.cpp               \
@@ -20,7 +21,6 @@
                   SecondaryTableController.cpp         \
                   SoftapController.cpp                 \
                   TetherController.cpp                 \
-                  ThrottleController.cpp               \
                   oem_iptables_hook.cpp                \
                   logwrapper.c                         \
                   main.cpp                             \
diff --git a/ClatdController.cpp b/ClatdController.cpp
new file mode 100644
index 0000000..ba4ca27
--- /dev/null
+++ b/ClatdController.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define LOG_TAG "ClatdController"
+#include <cutils/log.h>
+
+#include "ClatdController.h"
+
+ClatdController::ClatdController() {
+    mClatdPid = 0;
+}
+
+ClatdController::~ClatdController() {
+}
+
+int ClatdController::startClatd(char *interface) {
+    pid_t pid;
+
+    if(mClatdPid != 0) {
+        ALOGE("clatd already running");
+        errno = EBUSY;
+        return -1;
+    }
+
+    ALOGD("starting clatd");
+
+    if ((pid = fork()) < 0) {
+        ALOGE("fork failed (%s)", strerror(errno));
+        return -1;
+    }
+
+    if (!pid) {
+        char **args = (char **)malloc(sizeof(char *) * 4);
+        args[0] = (char *)"/system/bin/clatd";
+        args[1] = (char *)"-i";
+        args[2] = interface;
+        args[3] = NULL;
+
+        if (execv(args[0], args)) {
+            ALOGE("execv failed (%s)", strerror(errno));
+        }
+        ALOGE("Should never get here!");
+        free(args);
+        _exit(0);
+    } else {
+        mClatdPid = pid;
+        ALOGD("clatd started");
+    }
+
+    return 0;
+}
+
+int ClatdController::stopClatd() {
+    if (mClatdPid == 0) {
+        ALOGE("clatd already stopped");
+        return -1;
+    }
+
+    ALOGD("Stopping clatd");
+
+    kill(mClatdPid, SIGTERM);
+    waitpid(mClatdPid, NULL, 0);
+    mClatdPid = 0;
+
+    ALOGD("clatd stopped");
+
+    return 0;
+}
+
+bool ClatdController::isClatdStarted() {
+    pid_t waitpid_status;
+    if(mClatdPid == 0) {
+        return false;
+    }
+    waitpid_status = waitpid(mClatdPid, NULL, WNOHANG);
+    if(waitpid_status != 0) {
+        mClatdPid = 0; // child exited, don't call waitpid on it again
+    }
+    return waitpid_status == 0; // 0 while child is running
+}
diff --git a/ThrottleController.h b/ClatdController.h
similarity index 62%
rename from ThrottleController.h
rename to ClatdController.h
index 3538e03..f059c31 100644
--- a/ThrottleController.h
+++ b/ClatdController.h
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
-#ifndef _THROTTLE_CONTROLLER_H
-#define _THROTTLE_CONTROLLER_H
+#ifndef _CLATD_CONTROLLER_H
+#define _CLATD_CONTROLLER_H
 
-class ThrottleController {
+class ClatdController {
+    pid_t mClatdPid;
+
 public:
-    static int setInterfaceThrottle(const char *iface, int rxKbps, int txKbps);
-    static int getInterfaceRxThrottle(const char *iface, int *rx);
-    static int getInterfaceTxThrottle(const char *iface, int *tx);
+    ClatdController();
+    virtual ~ClatdController();
 
-private:
-    static int runTcCmd(const char *cmd);
-    static void reset(const char *iface);
+    int startClatd(char *interface);
+    int stopClatd();
+    bool isClatdStarted();
 };
 
 #endif
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 7b82682..8d113e8 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -35,7 +35,6 @@
 
 #include "CommandListener.h"
 #include "ResponseCode.h"
-#include "ThrottleController.h"
 #include "BandwidthController.h"
 #include "IdletimerController.h"
 #include "SecondaryTableController.h"
@@ -53,6 +52,7 @@
 ResolverController *CommandListener::sResolverCtrl = NULL;
 SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL;
 FirewallController *CommandListener::sFirewallCtrl = NULL;
+ClatdController *CommandListener::sClatdCtrl = NULL;
 
 /**
  * List of module chains to be created, along with explicit ordering. ORDERING
@@ -136,6 +136,7 @@
     registerCmd(new IdletimerControlCmd());
     registerCmd(new ResolverCmd());
     registerCmd(new FirewallCmd());
+    registerCmd(new ClatdCmd());
 
     if (!sSecondaryTableCtrl)
         sSecondaryTableCtrl = new SecondaryTableController();
@@ -157,6 +158,8 @@
         sFirewallCtrl = new FirewallController();
     if (!sInterfaceCtrl)
         sInterfaceCtrl = new InterfaceController();
+    if (!sClatdCtrl)
+        sClatdCtrl = new ClatdController();
 
     /*
      * This is the only time we touch top-level chains in iptables; controllers
@@ -278,44 +281,6 @@
         cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
         free(msg);
         return 0;
-    } else if (!strcmp(argv[1], "getthrottle")) {
-        if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError,
-                    "Usage: interface getthrottle <interface> <rx|tx>", false);
-            return 0;
-        }
-        int val = 0;
-        int rc = 0;
-        int voldRc = ResponseCode::InterfaceRxThrottleResult;
-
-        if (!strcmp(argv[3], "rx")) {
-            rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val);
-        } else {
-            rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val);
-            voldRc = ResponseCode::InterfaceTxThrottleResult;
-        }
-        if (rc) {
-            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true);
-        } else {
-            char *msg = NULL;
-            asprintf(&msg, "%u", val);
-            cli->sendMsg(voldRc, msg, false);
-            free(msg);
-            return 0;
-        }
-        return 0;
-    } else if (!strcmp(argv[1], "setthrottle")) {
-        if (argc != 5) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError,
-                    "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false);
-            return 0;
-        }
-        if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) {
-            cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true);
-        } else {
-            cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false);
-        }
-        return 0;
     } else if (!strcmp(argv[1], "driver")) {
         int rc;
         char *rbuf;
@@ -823,11 +788,17 @@
 
 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
                                         int argc, char **argv) {
-    int rc = 0, flag = 0;
+    int rc = ResponseCode::SoftapStatusResult;
+    int flag = 0;
     char *retbuf = NULL;
 
+    if (sSoftapCtrl == NULL) {
+      cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
+      return -1;
+    }
     if (argc < 2) {
-        cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false);
+        cli->sendMsg(ResponseCode::CommandSyntaxError,
+                     "Missing argument in a SoftAP command", false);
         return 0;
     }
 
@@ -837,31 +808,23 @@
         rc = sSoftapCtrl->stopSoftap();
     } else if (!strcmp(argv[1], "fwreload")) {
         rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
-    } else if (!strcmp(argv[1], "clients")) {
-        rc = sSoftapCtrl->clientsSoftap(&retbuf);
-        if (!rc) {
-            cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);
-            free(retbuf);
-            return 0;
-        }
     } else if (!strcmp(argv[1], "status")) {
-        asprintf(&retbuf, "Softap service %s",
-                 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
-        cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
+        asprintf(&retbuf, "Softap service %s running",
+                 (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
+        cli->sendMsg(rc, retbuf, false);
         free(retbuf);
         return 0;
     } else if (!strcmp(argv[1], "set")) {
         rc = sSoftapCtrl->setSoftap(argc, argv);
     } else {
-        cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
         return 0;
     }
 
-    if (!rc) {
-        cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false);
-    } else {
-        cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
-    }
+    if (rc >= 400 && rc < 600)
+      cli->sendMsg(rc, "SoftAP command has failed", false);
+    else
+      cli->sendMsg(rc, "Ok", false);
 
     return 0;
 }
@@ -887,9 +850,10 @@
                     "Wrong number of arguments to resolver setdefaultif", false);
             return 0;
         }
-    } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..."
-        if (argc >= 4) {
-            rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3);
+    } else if (!strcmp(argv[1], "setifdns")) {
+        // "resolver setifdns <iface> <domains> <dns1> <dns2> ..."
+        if (argc >= 5) {
+            rc = sResolverCtrl->setInterfaceDnsServers(argv[2], argv[3], &argv[4], argc - 4);
         } else {
             cli->sendMsg(ResponseCode::CommandSyntaxError,
                     "Wrong number of arguments to resolver setifdns", false);
@@ -1439,3 +1403,44 @@
     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
     return 0;
 }
+
+CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
+}
+
+int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
+                                                            char **argv) {
+    int rc = 0;
+    if (argc < 2) {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
+        return 0;
+    }
+
+    if(!strcmp(argv[1], "stop")) {
+        rc = sClatdCtrl->stopClatd();
+    } else if (!strcmp(argv[1], "status")) {
+        char *tmp = NULL;
+
+        asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted() ?
+                                                        "started" : "stopped"));
+        cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
+        free(tmp);
+        return 0;
+    } else if(!strcmp(argv[1], "start")) {
+        if (argc < 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
+            return 0;
+        }
+        rc = sClatdCtrl->startClatd(argv[2]);
+    } else {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
+        return 0;
+    }
+
+    if (!rc) {
+        cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
+    } else {
+        cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
+    }
+
+    return 0;
+}
diff --git a/CommandListener.h b/CommandListener.h
index 6cae13e..e8d92a8 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -30,6 +30,7 @@
 #include "ResolverController.h"
 #include "SecondaryTableController.h"
 #include "FirewallController.h"
+#include "ClatdController.h"
 
 class CommandListener : public FrameworkListener {
     static TetherController *sTetherCtrl;
@@ -42,6 +43,7 @@
     static ResolverController *sResolverCtrl;
     static SecondaryTableController *sSecondaryTableCtrl;
     static FirewallController *sFirewallCtrl;
+    static ClatdController *sClatdCtrl;
 
 public:
     CommandListener();
@@ -136,6 +138,13 @@
         int sendGenericOkFail(SocketClient *cli, int cond);
         static FirewallRule parseRule(const char* arg);
     };
+
+    class ClatdCmd : public NetdCommand {
+    public:
+        ClatdCmd();
+        virtual ~ClatdCmd() {}
+        int runCommand(SocketClient *c, int argc, char ** argv);
+    };
 };
 
 #endif
diff --git a/ResolverController.cpp b/ResolverController.cpp
index 23554e8..08a54a7 100644
--- a/ResolverController.cpp
+++ b/ResolverController.cpp
@@ -37,12 +37,12 @@
     return 0;
 }
 
-int ResolverController::setInterfaceDnsServers(const char* iface, char** servers, int numservers) {
+int ResolverController::setInterfaceDnsServers(const char* iface, const char* domains,
+        char** servers, int numservers) {
     if (DBG) {
         ALOGD("setInterfaceDnsServers iface = %s\n", iface);
     }
-
-    _resolv_set_nameservers_for_iface(iface, servers, numservers);
+    _resolv_set_nameservers_for_iface(iface, servers, numservers, domains);
 
     return 0;
 }
diff --git a/ResolverController.h b/ResolverController.h
index c6260da..9cb88ab 100644
--- a/ResolverController.h
+++ b/ResolverController.h
@@ -26,7 +26,8 @@
     virtual ~ResolverController() {};
 
     int setDefaultInterface(const char* iface);
-    int setInterfaceDnsServers(const char* iface, char** servers, int numservers);
+    int setInterfaceDnsServers(const char* iface, const char * domains, char** servers,
+            int numservers);
     int setInterfaceAddress(const char* iface, struct in_addr* addr);
     int flushDefaultDnsCache();
     int flushInterfaceDnsCache(const char* iface);
diff --git a/ResponseCode.h b/ResponseCode.h
index c6f5c2d..7689ef8 100644
--- a/ResponseCode.h
+++ b/ResponseCode.h
@@ -44,6 +44,7 @@
     static const int QuotaCounterResult        = 220;
     static const int TetheringStatsResult      = 221;
     static const int DnsProxyQueryResult       = 222;
+    static const int ClatdStatusResult         = 223;
 
     // 400 series - The command was accepted but the requested action
     // did not take place.
diff --git a/SoftapController.cpp b/SoftapController.cpp
index 7c7b2d0..21274f4 100644
--- a/SoftapController.cpp
+++ b/SoftapController.cpp
@@ -38,129 +38,101 @@
 #include <netutils/ifc.h>
 #include <private/android_filesystem_config.h>
 #include "wifi.h"
+#include "ResponseCode.h"
 
 #include "SoftapController.h"
 
 static const char HOSTAPD_CONF_FILE[]    = "/data/misc/wifi/hostapd.conf";
+static const char HOSTAPD_BIN_FILE[]    = "/system/bin/hostapd";
 
-SoftapController::SoftapController() {
-    mPid = 0;
-    mSock = socket(AF_INET, SOCK_DGRAM, 0);
-    if (mSock < 0)
-        ALOGE("Failed to open socket");
-}
+SoftapController::SoftapController()
+    : mPid(0) {}
 
 SoftapController::~SoftapController() {
-    if (mSock >= 0)
-        close(mSock);
 }
 
 int SoftapController::startSoftap() {
     pid_t pid = 1;
-    int ret = 0;
 
     if (mPid) {
-        ALOGE("Softap already started");
-        return 0;
-    }
-    if (mSock < 0) {
-        ALOGE("Softap startap - failed to open socket");
-        return -1;
+        ALOGE("SoftAP is already running");
+        return ResponseCode::SoftapStatusResult;
     }
 
     if ((pid = fork()) < 0) {
         ALOGE("fork failed (%s)", strerror(errno));
-        return -1;
+        return ResponseCode::ServiceStartFailed;
     }
 
     if (!pid) {
         ensure_entropy_file_exists();
-        if (execl("/system/bin/hostapd", "/system/bin/hostapd",
+        if (execl(HOSTAPD_BIN_FILE, HOSTAPD_BIN_FILE,
                   "-e", WIFI_ENTROPY_FILE,
                   HOSTAPD_CONF_FILE, (char *) NULL)) {
             ALOGE("execl failed (%s)", strerror(errno));
         }
-        ALOGE("Should never get here!");
-        return -1;
+        ALOGE("SoftAP failed to start");
+        return ResponseCode::ServiceStartFailed;
     } else {
         mPid = pid;
-        ALOGD("Softap startap - Ok");
+        ALOGD("SoftAP started successfully");
         usleep(AP_BSS_START_DELAY);
     }
-    return ret;
-
+    return ResponseCode::SoftapStatusResult;
 }
 
 int SoftapController::stopSoftap() {
 
     if (mPid == 0) {
-        ALOGE("Softap already stopped");
-        return 0;
+        ALOGE("SoftAP is not running");
+        return ResponseCode::SoftapStatusResult;
     }
 
-    ALOGD("Stopping Softap service");
+    ALOGD("Stopping the SoftAP service...");
     kill(mPid, SIGTERM);
     waitpid(mPid, NULL, 0);
 
-    if (mSock < 0) {
-        ALOGE("Softap stopap - failed to open socket");
-        return -1;
-    }
     mPid = 0;
-    ALOGD("Softap service stopped");
+    ALOGD("SoftAP stopped successfully");
     usleep(AP_BSS_STOP_DELAY);
-    return 0;
+    return ResponseCode::SoftapStatusResult;
 }
 
 bool SoftapController::isSoftapStarted() {
-    return (mPid != 0 ? true : false);
+    return (mPid != 0);
 }
 
 /*
  * Arguments:
- *      argv[2] - wlan interface
- *      argv[3] - SSID
- *	argv[4] - Security
- *	argv[5] - Key
- *	argv[6] - Channel
- *	argv[7] - Preamble
- *	argv[8] - Max SCB
+ *  argv[2] - wlan interface
+ *  argv[3] - SSID
+ *  argv[4] - Security
+ *  argv[5] - Key
  */
 int SoftapController::setSoftap(int argc, char *argv[]) {
     char psk_str[2*SHA256_DIGEST_LENGTH+1];
-    int ret = 0, i = 0, fd;
-    char *ssid, *iface;
+    int ret = ResponseCode::SoftapStatusResult;
+    int i = 0;
+    int fd;
 
-    if (mSock < 0) {
-        ALOGE("Softap set - failed to open socket");
-        return -1;
-    }
     if (argc < 4) {
-        ALOGE("Softap set - missing arguments");
-        return -1;
+        ALOGE("Softap set is missing arguments. Please use: softap <wlan iface> <SSID> <wpa2?-psk|open> <passphrase>");
+        return ResponseCode::CommandSyntaxError;
     }
 
-    iface = argv[2];
-
     char *wbuf = NULL;
     char *fbuf = NULL;
 
-    if (argc > 3) {
-        ssid = argv[3];
-    } else {
-        ssid = (char *)"AndroidAP";
-    }
-
     asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="
             "/data/misc/wifi/hostapd\nssid=%s\nchannel=6\nieee80211n=1\n",
-            iface, ssid);
+            argv[2], argv[3]);
 
     if (argc > 4) {
         if (!strcmp(argv[4], "wpa-psk")) {
-            generatePsk(ssid, argv[5], psk_str);
+            generatePsk(argv[3], argv[5], psk_str);
             asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf, psk_str);
         } else if (!strcmp(argv[4], "wpa2-psk")) {
-            generatePsk(ssid, argv[5], psk_str);
+            generatePsk(argv[3], argv[5], psk_str);
             asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf, psk_str);
         } else if (!strcmp(argv[4], "open")) {
             asprintf(&fbuf, "%s", wbuf);
@@ -174,11 +146,11 @@
         ALOGE("Cannot update \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
         free(wbuf);
         free(fbuf);
-        return -1;
+        return ResponseCode::OperationFailed;
     }
     if (write(fd, fbuf, strlen(fbuf)) < 0) {
         ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
-        ret = -1;
+        ret = ResponseCode::OperationFailed;
     }
     free(wbuf);
     free(fbuf);
@@ -189,7 +161,7 @@
                 HOSTAPD_CONF_FILE, strerror(errno));
         close(fd);
         unlink(HOSTAPD_CONF_FILE);
-        return -1;
+        return ResponseCode::OperationFailed;
     }
 
     if (fchown(fd, AID_SYSTEM, AID_WIFI) < 0) {
@@ -197,13 +169,47 @@
                 HOSTAPD_CONF_FILE, AID_WIFI, strerror(errno));
         close(fd);
         unlink(HOSTAPD_CONF_FILE);
-        return -1;
+        return ResponseCode::OperationFailed;
     }
 
     close(fd);
     return ret;
 }
 
+/*
+ * Arguments:
+ *	argv[2] - interface name
+ *	argv[3] - AP or P2P or STA
+ */
+int SoftapController::fwReloadSoftap(int argc, char *argv[])
+{
+    int i = 0;
+    char *fwpath = NULL;
+
+    if (argc < 4) {
+        ALOGE("SoftAP fwreload is missing arguments. Please use: softap <wlan iface> <AP|P2P|STA>");
+        return ResponseCode::CommandSyntaxError;
+    }
+
+    if (strcmp(argv[3], "AP") == 0) {
+        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
+    } else if (strcmp(argv[3], "P2P") == 0) {
+        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
+    } else if (strcmp(argv[3], "STA") == 0) {
+        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
+    }
+    if (!fwpath)
+        return ResponseCode::CommandParameterError;
+    if (wifi_change_fw_path((const char *)fwpath)) {
+        ALOGE("Softap fwReload failed");
+        return ResponseCode::OperationFailed;
+    }
+    else {
+        ALOGD("Softap fwReload - Ok");
+    }
+    return ResponseCode::SoftapStatusResult;
+}
+
 void SoftapController::generatePsk(char *ssid, char *passphrase, char *psk_str) {
     unsigned char psk[SHA256_DIGEST_LENGTH];
     int j;
@@ -212,55 +218,6 @@
             reinterpret_cast<const unsigned char *>(ssid), strlen(ssid),
             4096, SHA256_DIGEST_LENGTH, psk);
     for (j=0; j < SHA256_DIGEST_LENGTH; j++) {
-        sprintf(&psk_str[j<<1], "%02x", psk[j]);
+        sprintf(&psk_str[j*2], "%02x", psk[j]);
     }
-    psk_str[j<<1] = '\0';
-}
-
-
-/*
- * Arguments:
- *	argv[2] - interface name
- *	argv[3] - AP or STA
- */
-int SoftapController::fwReloadSoftap(int argc, char *argv[])
-{
-    int ret, i = 0;
-    char *iface;
-    char *fwpath;
-
-    if (mSock < 0) {
-        ALOGE("Softap fwrealod - failed to open socket");
-        return -1;
-    }
-    if (argc < 4) {
-        ALOGE("Softap fwreload - missing arguments");
-        return -1;
-    }
-
-    iface = argv[2];
-
-    if (strcmp(argv[3], "AP") == 0) {
-        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
-    } else if (strcmp(argv[3], "P2P") == 0) {
-        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
-    } else {
-        fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
-    }
-    if (!fwpath)
-        return -1;
-    ret = wifi_change_fw_path((const char *)fwpath);
-    if (ret) {
-        ALOGE("Softap fwReload - failed: %d", ret);
-    }
-    else {
-        ALOGD("Softap fwReload - Ok");
-    }
-    return ret;
-}
-
-int SoftapController::clientsSoftap(char **retbuf)
-{
-    /* TODO: implement over hostapd */
-    return 0;
 }
diff --git a/SoftapController.h b/SoftapController.h
index 57241b9..38ff8ff 100644
--- a/SoftapController.h
+++ b/SoftapController.h
@@ -27,11 +27,6 @@
 #define AP_DRIVER_START_DELAY	800000
 
 class SoftapController {
-    pid_t mPid;
-    int mSock;
-
-    int addParam(int pos, const char *cmd, const char *arg);
-    int setCommand(char *iface, const char *fname, unsigned buflen=0);
 public:
     SoftapController();
     virtual ~SoftapController();
@@ -40,9 +35,10 @@
     int stopSoftap();
     bool isSoftapStarted();
     int setSoftap(int argc, char *argv[]);
-    void generatePsk(char *ssid, char *passphrase, char *psk);
     int fwReloadSoftap(int argc, char *argv[]);
-    int clientsSoftap(char **retbuf);
+private:
+    pid_t mPid;
+    void generatePsk(char *ssid, char *passphrase, char *psk);
 };
 
 #endif
diff --git a/TetherController.cpp b/TetherController.cpp
index 5f571a1..d067f11 100644
--- a/TetherController.cpp
+++ b/TetherController.cpp
@@ -158,12 +158,12 @@
             ALOGE("execl failed (%s)", strerror(errno));
         }
         ALOGE("Should never get here!");
-        free(args);
-        return 0;
+        _exit(-1);
     } else {
         close(pipefd[0]);
         mDaemonPid = pid;
         mDaemonFd = pipefd[1];
+        applyDnsInterfaces();
         ALOGD("Tethering services running");
     }
 
@@ -217,11 +217,11 @@
 
         char *args[10];
         int argc = 0;
-        args[argc++] = "/system/bin/dhcpcd";
+        args[argc++] = (char *)"/system/bin/dhcpcd";
         char host_name[128];
         if (property_get("net.hostname", host_name, NULL) && (host_name[0] != '\0'))
         {
-            args[argc++] = "-h";
+            args[argc++] = (char *)"-h";
             args[argc++] = host_name;
         }
         args[argc++] = (char*)iface;
@@ -233,7 +233,7 @@
         // TODO(BT) inform parent of the failure.
         //          Parent process need wait for child to report error status
         //          before it set mDhcpcdPid and return 0.
-        exit(-1);
+        _exit(-1);
     } else {
         mDhcpcdPid = pid;
         ALOGD("Reverse Tethering running, pid:%d", pid);
@@ -308,19 +308,67 @@
     return mDnsForwarders;
 }
 
-int TetherController::tetherInterface(const char *interface) {
-    mInterfaces->push_back(strdup(interface));
+int TetherController::applyDnsInterfaces() {
+    int i;
+    char daemonCmd[MAX_CMD_SIZE];
+
+    strcpy(daemonCmd, "update_ifaces");
+    int cmdLen = strlen(daemonCmd);
+    InterfaceCollection::iterator it;
+    bool haveInterfaces = false;
+
+    for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
+        cmdLen += (strlen(*it) + 1);
+        if (cmdLen + 1 >= MAX_CMD_SIZE) {
+            ALOGD("Too many DNS ifaces listed");
+            break;
+        }
+
+        strcat(daemonCmd, ":");
+        strcat(daemonCmd, *it);
+        haveInterfaces = true;
+    }
+
+    if ((mDaemonFd != -1) && haveInterfaces) {
+        ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
+        if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
+            ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
+            return -1;
+        }
+    }
     return 0;
 }
 
+int TetherController::tetherInterface(const char *interface) {
+    ALOGD("tetherInterface(%s)", interface);
+    mInterfaces->push_back(strdup(interface));
+
+    if (applyDnsInterfaces()) {
+        InterfaceCollection::iterator it;
+        for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
+            if (!strcmp(interface, *it)) {
+                free(*it);
+                mInterfaces->erase(it);
+                break;
+            }
+        }
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
 int TetherController::untetherInterface(const char *interface) {
     InterfaceCollection::iterator it;
 
+    ALOGD("untetherInterface(%s)", interface);
+
     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
         if (!strcmp(interface, *it)) {
             free(*it);
             mInterfaces->erase(it);
-            return 0;
+
+            return applyDnsInterfaces();
         }
     }
     errno = ENOENT;
diff --git a/TetherController.h b/TetherController.h
index d3106eb..02cd412 100644
--- a/TetherController.h
+++ b/TetherController.h
@@ -52,6 +52,9 @@
     int tetherInterface(const char *interface);
     int untetherInterface(const char *interface);
     InterfaceCollection *getTetheredInterfaceList();
+
+private:
+    int applyDnsInterfaces();
 };
 
 #endif
diff --git a/ThrottleController.cpp b/ThrottleController.cpp
deleted file mode 100644
index 5bd7ad5..0000000
--- a/ThrottleController.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/pkt_sched.h>
-
-#define LOG_TAG "ThrottleController"
-#include <cutils/log.h>
-
-
-#include "ThrottleController.h"
-#include "NetdConstants.h"
-
-extern "C" int system_nosh(const char *command);
-extern "C" int ifc_init(void);
-extern "C" int ifc_up(const char *name);
-extern "C" int ifc_down(const char *name);
-
-int ThrottleController::runTcCmd(const char *cmd) {
-    char *buffer;
-    size_t len = strnlen(cmd, 255);
-    int res;
-
-    if (len == 255) {
-        ALOGE("tc command too long");
-        errno = E2BIG;
-        return -1;
-    }
-
-    asprintf(&buffer, "%s %s", TC_PATH, cmd);
-    res = system_nosh(buffer);
-    free(buffer);
-    return res;
-}
-
-int ThrottleController::setInterfaceThrottle(const char *iface, int rxKbps, int txKbps) {
-    char cmd[512];
-    char ifn[65];
-    int rc;
-
-    memset(ifn, 0, sizeof(ifn));
-    strncpy(ifn, iface, sizeof(ifn)-1);
-
-    if (txKbps == -1) {
-        reset(ifn);
-        return 0;
-    }
-
-    /*
-     *
-     * Target interface configuration
-     *
-     */
-
-    /*
-     * Add root qdisc for the interface
-     */
-    sprintf(cmd, "qdisc add dev %s root handle 1: htb default 1 r2q 1000", ifn);
-    if (runTcCmd(cmd)) {
-        ALOGE("Failed to add root qdisc (%s)", strerror(errno));
-        goto fail;
-    }
-
-    /*
-     * Add our egress throttling class
-     */
-    sprintf(cmd, "class add dev %s parent 1: classid 1:1 htb rate %dkbit", ifn, txKbps);
-    if (runTcCmd(cmd)) {
-        ALOGE("Failed to add egress throttling class (%s)", strerror(errno));
-        goto fail;
-    }
-
-    /*
-     * Bring up the IFD device
-     */
-    ifc_init();
-    if (ifc_up("ifb0")) {
-        ALOGE("Failed to up ifb0 (%s)", strerror(errno));
-        goto fail;
-    }
-
-    /*
-     * Add root qdisc for IFD
-     */
-    sprintf(cmd, "qdisc add dev ifb0 root handle 1: htb default 1 r2q 1000");
-    if (runTcCmd(cmd)) {
-        ALOGE("Failed to add root ifb qdisc (%s)", strerror(errno));
-        goto fail;
-    }
-
-    /*
-     * Add our ingress throttling class
-     */
-    sprintf(cmd, "class add dev ifb0 parent 1: classid 1:1 htb rate %dkbit", rxKbps);
-    if (runTcCmd(cmd)) {
-        ALOGE("Failed to add ingress throttling class (%s)", strerror(errno));
-        goto fail;
-    }
-
-    /*
-     * Add ingress qdisc for pkt redirection
-     */
-    sprintf(cmd, "qdisc add dev %s ingress", ifn);
-    if (runTcCmd(cmd)) {
-        ALOGE("Failed to add ingress qdisc (%s)", strerror(errno));
-        goto fail;
-    }
-
-    /*
-     * Add filter to link <ifn> -> ifb0
-     */
-    sprintf(cmd, "filter add dev %s parent ffff: protocol ip prio 10 u32 match "
-            "u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0", ifn);
-    if (runTcCmd(cmd)) {
-        ALOGE("Failed to add ifb filter (%s)", strerror(errno));
-        goto fail;
-    }
-
-    return 0;
-fail:
-    reset(ifn);
-    return -1;
-}
-
-void ThrottleController::reset(const char *iface) {
-    char cmd[128];
-
-    sprintf(cmd, "qdisc del dev %s root", iface);
-    runTcCmd(cmd);
-    sprintf(cmd, "qdisc del dev %s ingress", iface);
-    runTcCmd(cmd);
-
-    runTcCmd("qdisc del dev ifb0 root");
-}
-
-int ThrottleController::getInterfaceRxThrottle(const char *iface, int *rx) {
-    *rx = 0;
-    return 0;
-}
-
-int ThrottleController::getInterfaceTxThrottle(const char *iface, int *tx) {
-    *tx = 0;
-    return 0;
-}