resolved conflicts for merge of 80adaddf to master

Change-Id: I53c036b229352430c3faf57ce1d02fa889827690
diff --git a/Android.mk b/Android.mk
index c6deaab..8045ad7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,28 +10,31 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=                                      \
-                  main.cpp                             \
+                  BandwidthController.cpp              \
                   CommandListener.cpp                  \
                   DnsProxyListener.cpp                 \
-                  NetdCommand.cpp                      \
-                  NetlinkManager.cpp                   \
-                  NetlinkHandler.cpp                   \
-                  logwrapper.c                         \
-                  TetherController.cpp                 \
                   NatController.cpp                    \
-                  PppController.cpp                    \
+                  NetdCommand.cpp                      \
+                  NetlinkHandler.cpp                   \
+                  NetlinkManager.cpp                   \
                   PanController.cpp                    \
+                  PppController.cpp                    \
+                  ResolverController.cpp               \
                   SoftapController.cpp                 \
-                  UsbController.cpp                    \
+                  TetherController.cpp                 \
                   ThrottleController.cpp               \
-                  ResolverController.cpp
+                  logwrapper.c                         \
+                  main.cpp                             \
+
 
 LOCAL_MODULE:= netd
 
 LOCAL_C_INCLUDES := $(KERNEL_HEADERS) \
                     $(LOCAL_PATH)/../bluetooth/bluedroid/include \
                     $(LOCAL_PATH)/../bluetooth/bluez-clean-headers \
-                    external/openssl/include
+                    external/openssl/include \
+                    external/stlport/stlport \
+                    bionic
 
 LOCAL_CFLAGS :=
 ifdef WIFI_DRIVER_FW_STA_PATH
@@ -41,7 +44,7 @@
 LOCAL_CFLAGS += -DWIFI_DRIVER_FW_AP_PATH=\"$(WIFI_DRIVER_FW_AP_PATH)\"
 endif
 
-LOCAL_SHARED_LIBRARIES := libsysutils libcutils libnetutils libcrypto
+LOCAL_SHARED_LIBRARIES := libstlport libsysutils libcutils libnetutils libcrypto
 
 ifeq ($(BOARD_HAVE_BLUETOOTH),true)
   LOCAL_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES) libbluedroid
diff --git a/BandwidthController.cpp b/BandwidthController.cpp
new file mode 100644
index 0000000..50db1ec
--- /dev/null
+++ b/BandwidthController.cpp
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2011 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 <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 "BandwidthController"
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+extern "C" int logwrap(int argc, const char **argv, int background);
+
+#include "BandwidthController.h"
+
+const int BandwidthController::MAX_CMD_LEN = 1024;
+const int BandwidthController::MAX_IFACENAME_LEN = 64;
+const int BandwidthController::MAX_CMD_ARGS = 32;
+const char BandwidthController::IPTABLES_PATH[] = "/system/bin/iptables";
+const char BandwidthController::IP6TABLES_PATH[] = "/system/bin/ip6tables";
+
+/**
+ * Some comments about the rules:
+ *  * Ordering
+ *    - when an interface is marked as costly it should be INSERTED into the INPUT/OUTPUT chains.
+ *      E.g. "-I INPUT -i rmnet0 --goto costly"
+ *    - quota'd rules in the costly chain should be before penalty_box lookups.
+ *
+ * * global quota vs per interface quota
+ *   - global quota for all costly interfaces uses a single costly chain:
+ *    . initial rules
+ *      iptables -N costly
+ *      iptables -I INPUT -i iface0 --goto costly
+ *      iptables -I OUTPUT -o iface0 --goto costly
+ *      iptables -I costly -m quota \! --quota 500000 --jump REJECT --reject-with icmp-net-prohibited
+ *      iptables -A costly                            --jump penalty_box
+ *      iptables -A costly -m owner --socket-exists
+ *    . adding a new iface to this, E.g.:
+ *      iptables -I INPUT -i iface1 --goto costly
+ *      iptables -I OUTPUT -o iface1 --goto costly
+ *
+ *   - quota per interface. This is achieve by having "costly" chains per quota.
+ *     E.g. adding a new costly interface iface0 with its own quota:
+ *      iptables -N costly_iface0
+ *      iptables -I INPUT -i iface0 --goto costly_iface0
+ *      iptables -I OUTPUT -o iface0 --goto costly_iface0
+ *      iptables -A costly_iface0 -m quota \! --quota 500000 --jump REJECT --reject-with icmp-net-prohibited
+ *      iptables -A costly_iface0                            --jump penalty_box
+ *      iptables -A costly_iface0 -m owner --socket-exists
+ *
+ * * penalty_box handling:
+ *  - only one penalty_box for all interfaces
+ *   E.g  Adding an app:
+ *    iptables -A penalty_box -m owner --uid-owner app_3 --jump REJECT --reject-with icmp-net-prohibited
+ */
+const char *BandwidthController::cleanupCommands[] = {
+    /* Cleanup rules. */
+    "-F",
+    "-t raw -F",
+    "-X costly",
+    "-X penalty_box",
+};
+
+const char *BandwidthController::setupCommands[] = {
+    /* Created needed chains. */
+    "-N costly",
+    "-N penalty_box",
+};
+
+const char *BandwidthController::basicAccountingCommands[] = {
+    "-F INPUT",
+    "-A INPUT -i lo --jump ACCEPT",
+    "-A INPUT -m owner --socket-exists", /* This is a tracking rule. */
+
+    "-F OUTPUT",
+    "-A OUTPUT -o lo --jump ACCEPT",
+    "-A OUTPUT -m owner --socket-exists", /* This is a tracking rule. */
+
+    "-F costly",
+    "-A costly --jump penalty_box",
+    "-A costly -m owner --socket-exists", /* This is a tracking rule. */
+    /* TODO(jpa): Figure out why iptables doesn't correctly return from this
+     * chain. For now, hack the chain exit with an ACCEPT.
+     */
+    "-A costly --jump ACCEPT",
+};
+
+BandwidthController::BandwidthController(void) {
+
+    char value[PROPERTY_VALUE_MAX];
+
+    property_get("persist.bandwidth.enable", value, "0");
+    if (!strcmp(value, "1")) {
+        enableBandwidthControl();
+    }
+
+}
+
+int BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling) {
+    int res = 0;
+    LOGD("runIpxtablesCmd(cmd=%s)", cmd);
+    res |= runIptablesCmd(cmd, rejectHandling, IptIpV4);
+    res |= runIptablesCmd(cmd, rejectHandling, IptIpV6);
+    return res;
+}
+
+int BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) {
+
+    memset(buffer, '\0', buffSize);  // strncpy() is not filling leftover with '\0'
+    strncpy(buffer, src, buffSize);
+    return buffer[buffSize - 1];
+}
+
+int BandwidthController::runIptablesCmd(const char *cmd, IptRejectOp rejectHandling, IptIpVer iptVer) {
+    char buffer[MAX_CMD_LEN];
+    const char *argv[MAX_CMD_ARGS];
+    int argc = 0;
+    char *next = buffer;
+    char *tmp;
+
+    std::string fullCmd = cmd;
+
+    if (rejectHandling == IptRejectAdd) {
+        fullCmd += " --jump REJECT --reject-with";
+        switch (iptVer) {
+        case IptIpV4:
+                fullCmd += " icmp-net-prohibited";
+                break;
+        case IptIpV6:
+                fullCmd += " icmp6-adm-prohibited";
+                break;
+        }
+    }
+
+    argc = 0;
+    argv[argc++] = iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH;
+    LOGD("About to run: %s %s", argv[0], fullCmd.c_str());
+
+    LOGD("runIpxtablesCmd(): fullCmd.c_str()=%s buffSize=%d", fullCmd.c_str(), sizeof(buffer));
+    if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) {
+        LOGE("iptables command too long");
+        return -1;
+    }
+
+    while ((tmp = strsep(&next, " "))) {
+        argv[argc++] = tmp;
+        if (argc >= MAX_CMD_ARGS) {
+            LOGE("iptables argument overflow");
+            return -1;
+        }
+    }
+
+    argv[argc] = NULL;
+    LOGD("runIpxtablesCmd(): argc=%d, argv[argc]=%p", argc, argv[argc]);
+    /* TODO(jpa): Once this stabilizes, remove logwrap() as it tends to wedge netd
+     * Then just talk directly to the kernel via rtnetlink.
+     */
+    for (int i = 0 ; i < argc; i++) {
+            LOGD("runIpxtablesCmd(): argv[%d]=%p:%s", i, argv[i], argv[i]?:"null");
+    }
+    return logwrap(argc, argv, 0);
+}
+
+int BandwidthController::enableBandwidthControl(void) {
+    int res;
+    /* Some of the initialCommands are allowed to fail */
+    runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, RunCmdFailureOk);
+    runCommands(sizeof(setupCommands) / sizeof(char*), setupCommands, RunCmdFailureOk);
+    res = runCommands(sizeof(basicAccountingCommands) / sizeof(char*), basicAccountingCommands, RunCmdFailureBad);
+    return res;
+
+}
+
+int BandwidthController::disableBandwidthControl(void) {
+    /* The cleanupCommands are allowed to fail. */
+    runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, RunCmdFailureOk);
+    return 0;
+}
+
+int BandwidthController::runCommands(int numCommands, const char *commands[], RunCmdErrHandling cmdErrHandling) {
+    int res = 0;
+    LOGD("runCommands(): %d commands", numCommands);
+    for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) {
+        res = runIpxtablesCmd(commands[cmdNum], IptRejectNoAdd);
+        if (res && cmdErrHandling != RunCmdFailureBad)
+            return res;
+    }
+    return cmdErrHandling == RunCmdFailureBad ? res : 0;
+}
+
+std::string BandwidthController::makeIptablesNaughtyCmd(IptOp op, int uid) {
+    std::string res;
+    char *convBuff;
+
+    switch (op) {
+        case IptOpInsert:
+            res = "-I";
+            break;
+        case IptOpReplace:
+            res = "-R";
+            break;
+        default:
+        case IptOpDelete:
+            res = "-D";
+            break;
+    }
+    res += " penalty_box";
+    asprintf(&convBuff, "%d", uid);
+    res += " -m owner --uid-owner ";
+    res += convBuff;
+    free(convBuff);
+    LOGD("makeIptablesNaughtyCmd() res=%s", res.c_str());
+    return res;
+}
+
+int BandwidthController::addNaughtyApps(int numUids, char *appUids[]) {
+    return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpAdd);
+}
+
+int BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) {
+    return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpRemove);
+}
+
+int BandwidthController::maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp) {
+    char cmd[MAX_CMD_LEN];
+    int uidNum;
+    const char *failLogTemplate;
+    IptOp op;
+    int appUids[numUids];
+    std::string naughtyCmd;
+    LOGD("manipulateNaughtyApps()");
+    switch (appOp) {
+    case NaughtyAppOpAdd:
+            op = IptOpInsert;
+            failLogTemplate = "Failed to add app uid %d to penalty box.";
+            break;
+    case NaughtyAppOpRemove:
+            op = IptOpDelete;
+            failLogTemplate = "Failed to delete app uid %d from penalty box.";
+            break;
+    }
+
+    for (uidNum = 0; uidNum < numUids; uidNum++) {
+        appUids[uidNum] = atol(appStrUids[uidNum]);
+        if (appUids[uidNum] == 0) {
+            LOGE(failLogTemplate, appUids[uidNum]);
+            goto fail_parse;
+        }
+    }
+    LOGD("manipulateNaughtyApps() got the appUids");
+
+    for (uidNum = 0; uidNum < numUids; uidNum++) {
+        naughtyCmd = makeIptablesNaughtyCmd(op, appUids[uidNum]);
+        if (runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd)) {
+            LOGE(failLogTemplate, appUids[uidNum]);
+            goto fail_with_uidNum;
+        }
+    }
+    return 0;
+
+fail_with_uidNum:
+    /* Try to remove the uid that failed in any case*/
+    naughtyCmd = makeIptablesNaughtyCmd(IptOpDelete, appUids[uidNum]);
+    runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd);
+fail_parse:
+    return -1;
+}
+
+std::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota) {
+    std::string res;
+    char convBuff[21]; // log10(2^64) ~ 20
+
+    LOGD("makeIptablesQuotaCmd(%d, %llu)", op, quota);
+
+    switch (op) {
+        case IptOpInsert:
+            res = "-I";
+            break;
+        case IptOpReplace:
+            res = "-R";
+            break;
+        default:
+        case IptOpDelete:
+            res = "-D";
+            break;
+    }
+    res += " costly";
+    if (costName) {
+        res += "_";
+        res += costName;
+    }
+    sprintf(convBuff, "%lld", quota);
+    /* TODO(jpa): Use -m quota2 --name " + costName + " ! --quota "
+     * once available.
+     */
+    res += " -m quota ! --quota ";
+    res += convBuff;
+    ;
+    // The requried --jump REJECT ... will be added later.
+    return res;
+}
+
+int BandwidthController::prepCostlyIface(const char *ifn, QuotaType quotaType) {
+    char cmd[MAX_CMD_LEN];
+    int res = 0;
+    std::string costString;
+    const char *costCString;
+
+    costString = "costly";
+    /* The "-N costly" is created upfront, no need to handle it here. */
+    switch (quotaType) {
+    case QuotaUnique:
+        costString += "_";
+        costString += ifn;
+        costCString = costString.c_str();
+        snprintf(cmd, sizeof(cmd), "-N %s", costCString);
+        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+        snprintf(cmd, sizeof(cmd), "-A %s -j penalty_box", costCString);
+        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+        snprintf(cmd, sizeof(cmd), "-A %s -m owner --socket-exists", costCString);
+        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+        /* TODO(jpa): Figure out why iptables doesn't correctly return from this
+         * chain. For now, hack the chain exit with an ACCEPT.
+         */
+        snprintf(cmd, sizeof(cmd), "-A %s --jump ACCEPT", costCString);
+        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+        break;
+    case QuotaShared:
+        costCString = costString.c_str();
+        break;
+    }
+
+    snprintf(cmd, sizeof(cmd), "-I INPUT -i %s --goto %s", ifn, costCString);
+    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+    snprintf(cmd, sizeof(cmd), "-I OUTPUT -o %s --goto %s", ifn, costCString);
+    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+    return res;
+}
+
+int BandwidthController::cleanupCostlyIface(const char *ifn, QuotaType quotaType) {
+    char cmd[MAX_CMD_LEN];
+    int res = 0;
+    std::string costString;
+    const char *costCString;
+
+    costString = "costly";
+    switch (quotaType) {
+    case QuotaUnique:
+        costString += "_";
+        costString += ifn;
+        costCString = costString.c_str();
+        break;
+    case QuotaShared:
+        costCString = costString.c_str();
+        break;
+    }
+
+    snprintf(cmd, sizeof(cmd), "-D INPUT -i %s --goto %s", ifn, costCString);
+    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+    snprintf(cmd, sizeof(cmd), "-D OUTPUT -o %s --goto %s", ifn, costCString);
+    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+
+    /* The "-N costly" is created upfront, no need to handle it here. */
+    if (quotaType == QuotaUnique) {
+        snprintf(cmd, sizeof(cmd), "-F %s", costCString);
+        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
+    }
+    return res;
+}
+
+int BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) {
+    char cmd[MAX_CMD_LEN];
+    char ifn[MAX_IFACENAME_LEN];
+    int res = 0;
+    std::string quotaCmd;
+    std::string ifaceName;;
+    const char *costName = NULL; /* Shared quota */
+    std::list<std::string>::iterator it;
+
+    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
+        LOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
+        return -1;
+    }
+    ifaceName = ifn;
+
+    if (maxBytes == -1) {
+        return removeInterfaceSharedQuota(ifn);
+    }
+
+    /* Insert ingress quota. */
+    for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) {
+        if (*it == ifaceName)
+            break;
+    }
+
+    if (it == sharedQuotaIfaces.end()) {
+        res |= prepCostlyIface(ifn, QuotaShared);
+        if (sharedQuotaIfaces.empty()) {
+            quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
+            res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
+            if (res) {
+                LOGE("Failed set quota rule.");
+                goto fail;
+            }
+            sharedQuotaBytes = maxBytes;
+        }
+        sharedQuotaIfaces.push_front(ifaceName);
+
+    }
+
+    if (maxBytes != sharedQuotaBytes) {
+        /* Instead of replacing, which requires being aware of the rules in
+         * the kernel, we just add a new one, then delete the older one.
+         */
+
+        quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
+        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
+
+        quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes);
+        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
+
+        if (res) {
+            LOGE("Failed replace quota rule.");
+            goto fail;
+        }
+        sharedQuotaBytes = maxBytes;
+    }
+    return 0;
+
+    fail:
+    /*
+     * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse
+     * rules in the kernel to see which ones need cleaning up.
+     * For now callers needs to choose if they want to "ndc bandwidth enable"
+     * which resets everything.
+     */
+    removeInterfaceSharedQuota(ifn);
+    return -1;
+}
+
+int BandwidthController::removeInterfaceSharedQuota(const char *iface) {
+    char ifn[MAX_IFACENAME_LEN];
+    int res = 0;
+    std::string ifaceName;
+    std::list<std::string>::iterator it;
+
+    if(StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
+        LOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
+        return -1;
+    }
+    ifaceName =ifn;
+
+    for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) {
+        if (*it == ifaceName)
+            break;
+    }
+    if (it == sharedQuotaIfaces.end()) {
+        LOGE("No such iface %s to delete.", ifn);
+        return -1;
+    }
+
+    res |= cleanupCostlyIface(ifn, QuotaShared);
+    sharedQuotaIfaces.erase(it);
+
+    if (sharedQuotaIfaces.empty()) {
+        std::string quotaCmd;
+        quotaCmd = makeIptablesQuotaCmd(IptOpDelete, NULL, sharedQuotaBytes);
+        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
+        sharedQuotaBytes = -1;
+    }
+
+    return res;
+}
+
+int BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) {
+    char ifn[MAX_IFACENAME_LEN];
+    int res = 0;
+    std::string ifaceName;
+    const char *costName;
+    std::list<QuotaInfo>::iterator it;
+    std::string quotaCmd;
+
+    if (maxBytes == -1) {
+        return removeInterfaceQuota(iface);
+    }
+
+    if(StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
+        LOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
+        return -1;
+    }
+    ifaceName = ifn;
+    costName = iface;
+
+
+    /* Insert ingress quota. */
+    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
+        if (it->first == ifaceName)
+            break;
+    }
+
+    if (it == quotaIfaces.end()) {
+        res |= prepCostlyIface(ifn, QuotaUnique);
+        quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
+        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
+        if (res) {
+            LOGE("Failed set quota rule.");
+            goto fail;
+        }
+
+        quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes));
+
+    } else {
+        /* Instead of replacing, which requires being aware of the rules in
+         * the kernel, we just add a new one, then delete the older one.
+         */
+        quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
+        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
+
+        quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, it->second);
+        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
+
+        if (res) {
+            LOGE("Failed replace quota rule.");
+            goto fail;
+        }
+        it->second = maxBytes;
+    }
+    return 0;
+
+    fail:
+    /*
+     * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse
+     * rules in the kernel to see which ones need cleaning up.
+     * For now callers needs to choose if they want to "ndc bandwidth enable"
+     * which resets everything.
+     */
+    removeInterfaceSharedQuota(ifn);
+    return -1;
+}
+
+int BandwidthController::removeInterfaceQuota(const char *iface) {
+
+    char ifn[MAX_IFACENAME_LEN];
+    int res = 0;
+    std::string ifaceName;
+    const char *costName;
+    std::list<QuotaInfo>::iterator it;
+
+    if(StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
+        LOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
+        return -1;
+    }
+    ifaceName = ifn;
+    costName = iface;
+
+    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
+        if (it->first == ifaceName)
+            break;
+    }
+
+    if (it == quotaIfaces.end()) {
+        LOGE("No such iface %s to delete.", ifn);
+        return -1;
+    }
+
+    /* This also removes the quota command of CostlyIface chain. */
+    res |= cleanupCostlyIface(ifn, QuotaUnique);
+
+    quotaIfaces.erase(it);
+
+    return res;
+}
diff --git a/BandwidthController.h b/BandwidthController.h
new file mode 100644
index 0000000..f4fce50
--- /dev/null
+++ b/BandwidthController.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+#ifndef _BANDWIDTH_CONTROLLER_H
+#define _BANDWIDTH_CONTROLLER_H
+
+#include <list>
+#include <string>
+#include <utility>  // for pair
+class BandwidthController {
+public:
+    BandwidthController();
+    int enableBandwidthControl(void);
+    int disableBandwidthControl(void);
+
+    int setInterfaceSharedQuota(const char *iface, int64_t bytes);
+    int removeInterfaceSharedQuota(const char *iface);
+
+    int setInterfaceQuota(const char *iface, int64_t bytes);
+    int removeInterfaceQuota(const char *iface);
+
+    int addNaughtyApps(int numUids, char *appUids[]);
+    int removeNaughtyApps(int numUids, char *appUids[]);
+
+
+protected:
+    typedef std::pair<std::string /*ifaceName*/, int64_t /*quota*/> QuotaInfo;
+    enum IptIpVer { IptIpV4, IptIpV6 };
+    enum IptOp { IptOpInsert, IptOpReplace, IptOpDelete };
+    enum IptRejectOp { IptRejectAdd, IptRejectNoAdd };
+    enum NaughtyAppOp { NaughtyAppOpAdd, NaughtyAppOpRemove };
+    enum QuotaType { QuotaUnique, QuotaShared };
+    enum RunCmdErrHandling { RunCmdFailureBad, RunCmdFailureOk };
+
+    int64_t sharedQuotaBytes;
+    std::list<std::string> sharedQuotaIfaces;
+
+    std::list<QuotaInfo> quotaIfaces;
+
+    std::list<int /*appUid*/> naughtyAppUids;
+    int maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp);
+
+    int prepCostlyIface(const char *ifn, QuotaType quotaType);
+    int cleanupCostlyIface(const char *ifn, QuotaType quotaType);
+
+    std::string makeIptablesNaughtyCmd(IptOp op, int uid);
+    std::string makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota);
+
+    /* Runs for both ipv4 and ipv6 iptables */
+    int runCommands(int numCommands, const char *commands[], RunCmdErrHandling cmdErrHandling);
+    /* Runs for both ipv4 and ipv6 iptables, appends -j REJECT --reject-with ...  */
+    static int runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling);
+    static int runIptablesCmd(const char *cmd, IptRejectOp rejectHandling, IptIpVer iptIpVer);
+
+    // Provides strncpy() + check overflow.
+    static int StrncpyAndCheck(char *buffer, const char *src, size_t buffSize);
+
+private:
+    static const char *cleanupCommands[];
+    static const char *setupCommands[];
+    static const char *basicAccountingCommands[];
+    static const int MAX_CMD_LEN;
+    static const int MAX_IFACENAME_LEN;
+    static const int MAX_CMD_ARGS;
+    static const char IPTABLES_PATH[];
+    static const char IP6TABLES_PATH[];
+
+};
+
+#endif
diff --git a/CommandListener.cpp b/CommandListener.cpp
index c6faea4..9236605 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -33,11 +33,14 @@
 #include "CommandListener.h"
 #include "ResponseCode.h"
 #include "ThrottleController.h"
+#include "BandwidthController.h"
 
 
 extern "C" int ifc_init(void);
+extern "C" int ifc_close(void);
 extern "C" int ifc_get_hwaddr(const char *name, void *ptr);
 extern "C" int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags);
+extern "C" int ifc_get_addr(const char *name, in_addr_t *addr);
 extern "C" int ifc_set_addr(const char *name, in_addr_t addr);
 extern "C" int ifc_set_prefixLength(const char *name, int prefixLength);
 extern "C" int ifc_up(const char *name);
@@ -50,7 +53,7 @@
 PppController *CommandListener::sPppCtrl = NULL;
 PanController *CommandListener::sPanCtrl = NULL;
 SoftapController *CommandListener::sSoftapCtrl = NULL;
-UsbController *CommandListener::sUsbCtrl = NULL;
+BandwidthController * CommandListener::sBandwidthCtrl = NULL;
 ResolverController *CommandListener::sResolverCtrl = NULL;
 
 CommandListener::CommandListener() :
@@ -63,7 +66,7 @@
     registerCmd(new PppdCmd());
     registerCmd(new PanCmd());
     registerCmd(new SoftapCmd());
-    registerCmd(new UsbCmd());
+    registerCmd(new BandwidthControlCmd());
     registerCmd(new ResolverCmd());
 
     if (!sTetherCtrl)
@@ -76,8 +79,8 @@
         sPanCtrl = new PanController();
     if (!sSoftapCtrl)
         sSoftapCtrl = new SoftapController();
-    if (!sUsbCtrl)
-        sUsbCtrl = new UsbController();
+    if (!sBandwidthCtrl)
+        sBandwidthCtrl = new BandwidthController();
     if (!sResolverCtrl)
         sResolverCtrl = new ResolverController();
 }
@@ -231,6 +234,7 @@
 
             if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
                 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
+                ifc_close();
                 return 0;
             }
 
@@ -262,6 +266,8 @@
             free(addr_s);
             free(flag_s);
             free(msg);
+
+            ifc_close();
             return 0;
         } else if (!strcmp(argv[1], "setcfg")) {
             // arglist: iface addr prefixLength [flags]
@@ -282,11 +288,13 @@
             ifc_init();
             if (ifc_set_addr(argv[2], addr.s_addr)) {
                 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
+                ifc_close();
                 return 0;
             }
 
             if (ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
                 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
+                ifc_close();
                 return 0;
             }
 
@@ -313,6 +321,7 @@
                     if (ifc_up(argv[2])) {
                         LOGE("Error upping interface");
                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
+                        ifc_close();
                         return 0;
                     }
                 } else if (!strcmp(flag, "down")) {
@@ -320,6 +329,7 @@
                     if (ifc_down(argv[2])) {
                         LOGE("Error downing interface");
                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
+                        ifc_close();
                         return 0;
                     }
                 } else if (!strcmp(flag, "broadcast")) {
@@ -328,10 +338,30 @@
                     LOGD("multicast flag ignored");
                 } else {
                     cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
+                    ifc_close();
                     return 0;
                 }
             }
+
             cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
+            ifc_close();
+            return 0;
+        } else if (!strcmp(argv[1], "clearaddrs")) {
+            // arglist: iface
+            unsigned count, addr;
+
+            //IPv4 only right now
+            LOGD("Clearing all IP addresses on %s", argv[2]);
+
+            ifc_init();
+            for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
+                if (ifc_get_addr(argv[2], &addr) < 0)
+                    break;
+                if (addr)
+                    ifc_set_addr(argv[2], 0);
+            }
+            ifc_close();
+            cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
             return 0;
         } else {
             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
@@ -341,6 +371,7 @@
     return 0;
 }
 
+
 CommandListener::ListTtysCmd::ListTtysCmd() :
                  NetdCommand("list_ttys") {
 }
@@ -623,6 +654,7 @@
 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
                                         int argc, char **argv) {
     int rc = 0, flag = 0;
+    char *retbuf = NULL;
 
     if (argc < 2) {
         cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false);
@@ -639,13 +671,18 @@
         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")) {
-        char *tmp = NULL;
-
-        asprintf(&tmp, "Softap service %s",
+        asprintf(&retbuf, "Softap service %s",
                  (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
-        cli->sendMsg(ResponseCode::SoftapStatusResult, tmp, false);
-        free(tmp);
+        cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
+        free(retbuf);
         return 0;
     } else if (!strcmp(argv[1], "set")) {
         rc = sSoftapCtrl->setSoftap(argc, argv);
@@ -663,44 +700,6 @@
     return 0;
 }
 
-CommandListener::UsbCmd::UsbCmd() :
-                 NetdCommand("usb") {
-}
-
-int CommandListener::UsbCmd::runCommand(SocketClient *cli, int argc, char **argv) {
-    int rc = 0;
-
-    if (argc < 2) {
-        cli->sendMsg(ResponseCode::CommandSyntaxError, "Usb Missing argument", false);
-        return 0;
-    }
-
-    if (!strcmp(argv[1], "startrndis")) {
-        rc = sUsbCtrl->startRNDIS();
-    } else if (!strcmp(argv[1], "stoprndis")) {
-        rc = sUsbCtrl->stopRNDIS();
-    } else if (!strcmp(argv[1], "rndisstatus")) {
-        char *tmp = NULL;
-
-        asprintf(&tmp, "Usb RNDIS %s",
-                (sUsbCtrl->isRNDISStarted() ? "started" : "stopped"));
-        cli->sendMsg(ResponseCode::UsbRNDISStatusResult, tmp, false);
-        free(tmp);
-        return 0;
-    } else {
-        cli->sendMsg(ResponseCode::CommandSyntaxError, "Usb Unknown cmd", false);
-        return 0;
-    }
-
-    if (!rc) {
-        cli->sendMsg(ResponseCode::CommandOkay, "Usb operation succeeded", false);
-    } else {
-        cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
-    }
-
-    return 0;
-}
-
 CommandListener::ResolverCmd::ResolverCmd() :
         NetdCommand("resolver") {
 }
@@ -810,3 +809,117 @@
     *tx = 0;
     return 0;
 }
+
+CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
+    NetdCommand("bandwidth") {
+}
+
+int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
+    int rc = 0;
+    LOGD("bwctrlcmd: argc=%d argv[0]=%s", argc, argv[0]);
+    if (argc < 2) {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
+        return 0;
+    }
+
+    if (!strcmp(argv[1], "enable")) {
+        rc = sBandwidthCtrl->enableBandwidthControl();
+    } else if (!strcmp(argv[1], "disable")) {
+        rc = sBandwidthCtrl->disableBandwidthControl();
+
+    } else if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: bandwidth removequota <interface>", false);
+            return 0;
+        }
+        rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
+
+    } else if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
+        if (argc != 4) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: bandwidth setquota <interface> <bytes>", false);
+            return 0;
+        }
+        rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
+
+    } else if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
+        if (argc < 4) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: bandwidth setquotas <bytes> <interface> ...", false);
+            return 0;
+        }
+        for (int q=3; argc >= 4; q++, argc--) {
+            rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
+            if (rc) {
+                char *msg;
+                asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
+                cli->sendMsg(ResponseCode::OperationFailed,
+                             msg, false);
+                free(msg);
+                break;
+            }
+        }
+
+    } else if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
+        if (argc < 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: bandwidth removequotas <interface> ...", false);
+            return 0;
+        }
+        for (int q=2; argc >= 3; q++, argc--) {
+            rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
+            if (rc) {
+                char *msg;
+                asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
+                cli->sendMsg(ResponseCode::OperationFailed,
+                             msg, false);
+                free(msg);
+                break;
+            }
+        }
+
+    } else if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: bandwidth removeiquota <interface>", false);
+            return 0;
+        }
+        rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
+
+    } else if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
+        if (argc != 4) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: bandwidth setiquota <interface> <bytes>", false);
+            return 0;
+        }
+        rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
+
+    } else if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
+        if (argc < 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: bandwidth addnaughtyapps <appUid> ...", false);
+            return 0;
+        }
+        rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
+
+    } else if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
+        if (argc < 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: bandwidth remnaughtyapps <appUid> ...", false);
+            return 0;
+        }
+        rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
+
+    } else {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
+        return 0;
+    }
+
+    if (!rc) {
+        cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
+    } else {
+        cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", true);
+    }
+    return 0;
+}
diff --git a/CommandListener.h b/CommandListener.h
index d60069e..05e990e 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -25,7 +25,7 @@
 #include "PppController.h"
 #include "PanController.h"
 #include "SoftapController.h"
-#include "UsbController.h"
+#include "BandwidthController.h"
 #include "ResolverController.h"
 
 class CommandListener : public FrameworkListener {
@@ -34,7 +34,7 @@
     static PppController *sPppCtrl;
     static PanController *sPanCtrl;
     static SoftapController *sSoftapCtrl;
-    static UsbController *sUsbCtrl;
+    static BandwidthController *sBandwidthCtrl;
     static ResolverController *sResolverCtrl;
 
 public:
@@ -45,13 +45,6 @@
 
     static int readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx);
 
-    class UsbCmd : public NetdCommand {
-    public:
-        UsbCmd();
-        virtual ~UsbCmd() {}
-        int runCommand(SocketClient *c, int argc, char ** argv);
-    };
-
     class SoftapCmd : public NetdCommand {
     public:
         SoftapCmd();
@@ -108,6 +101,13 @@
         int runCommand(SocketClient *c, int argc, char ** argv);
     };
 
+    class BandwidthControlCmd : public NetdCommand {
+    public:
+        BandwidthControlCmd();
+        virtual ~BandwidthControlCmd() {}
+        int runCommand(SocketClient *c, int argc, char ** argv);
+    };
+
     class ResolverCmd : public NetdCommand {
     public:
         ResolverCmd();
diff --git a/DnsProxyListener.cpp b/DnsProxyListener.cpp
index 2546b82..bcb961e 100644
--- a/DnsProxyListener.cpp
+++ b/DnsProxyListener.cpp
@@ -92,6 +92,7 @@
     if (!success) {
         LOGW("Error writing DNS result to client");
     }
+    mClient->decRef();
 }
 
 DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd() :
@@ -145,11 +146,11 @@
              service ? service : "[nullservice]");
     }
 
+    cli->incRef();
     DnsProxyListener::GetAddrInfoHandler* handler =
         new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints);
     handler->start();
 
-
     return 0;
 }
 
@@ -187,6 +188,7 @@
         return -1;
     }
 
+    cli->incRef();
     DnsProxyListener::GetHostByAddrHandler* handler =
             new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily);
     handler->start();
@@ -234,4 +236,5 @@
     if (!success) {
         LOGW("GetHostByAddrHandler: Error writing DNS result to client\n");
     }
+    mClient->decRef();
 }
diff --git a/DnsProxyListener.h b/DnsProxyListener.h
index 915f86d..1e24ebd 100644
--- a/DnsProxyListener.h
+++ b/DnsProxyListener.h
@@ -54,7 +54,7 @@
     private:
         void run();
         pthread_t mThread;
-        SocketClient* mClient;  // not owned
+        SocketClient* mClient;  // ref counted
         char* mHost;    // owned
         char* mService; // owned
         struct addrinfo* mHints;  // owned
@@ -86,7 +86,7 @@
     private:
         void run();
         pthread_t mThread;
-        SocketClient* mClient;  // not owned
+        SocketClient* mClient;  // ref counted
         void* mAddress;    // address to lookup; owned
         int   mAddressLen; // length of address to look up
         int   mAddressFamily;  // address family
diff --git a/NatController.cpp b/NatController.cpp
index ddb0499..8c719eb 100644
--- a/NatController.cpp
+++ b/NatController.cpp
@@ -70,12 +70,8 @@
 
     if (runIptablesCmd("-P INPUT ACCEPT"))
         return -1;
-    if (runIptablesCmd("-F INPUT"))
-        return -1;
     if (runIptablesCmd("-P OUTPUT ACCEPT"))
         return -1;
-    if (runIptablesCmd("-F OUTPUT"))
-        return -1;
     if (runIptablesCmd("-P FORWARD DROP"))
         return -1;
     if (runIptablesCmd("-F FORWARD"))
diff --git a/SoftapController.cpp b/SoftapController.cpp
index 1f42214..6039761 100644
--- a/SoftapController.cpp
+++ b/SoftapController.cpp
@@ -51,7 +51,7 @@
         close(mSock);
 }
 
-int SoftapController::setCommand(char *iface, const char *fname) {
+int SoftapController::setCommand(char *iface, const char *fname, unsigned buflen) {
     char tBuf[SOFTAP_MAX_BUFFER_SIZE];
     struct iwreq wrq;
     struct iw_priv_args *priv_ptr;
@@ -96,10 +96,10 @@
     }
 
     strncpy(wrq.ifr_name, iface, sizeof(wrq.ifr_name));
-    if (*mBuf != 0)
+    if ((buflen == 0) && (*mBuf != 0))
         wrq.u.data.length = strlen(mBuf) + 1;
     else
-        wrq.u.data.length = 0;
+        wrq.u.data.length = buflen;
     wrq.u.data.pointer = mBuf;
     wrq.u.data.flags = sub_cmd;
     ret = ioctl(mSock, cmd, &wrq);
@@ -348,3 +348,22 @@
     }
     return ret;
 }
+
+int SoftapController::clientsSoftap(char **retbuf)
+{
+    int ret;
+
+    if (mSock < 0) {
+        LOGE("Softap clients - failed to open socket");
+        return -1;
+    }
+    *mBuf = 0;
+    ret = setCommand(mIface, "AP_GET_STA_LIST", SOFTAP_MAX_BUFFER_SIZE);
+    if (ret) {
+        LOGE("Softap clients - failed: %d", ret);
+    } else {
+        asprintf(retbuf, "Softap clients:%s", mBuf);
+        LOGD("Softap clients:%s", mBuf);
+    }
+    return ret;
+}
diff --git a/SoftapController.h b/SoftapController.h
index 60236f8..7801577 100644
--- a/SoftapController.h
+++ b/SoftapController.h
@@ -34,7 +34,7 @@
     int mSock;
 
     int addParam(int pos, const char *cmd, const char *arg);
-    int setCommand(char *iface, const char *fname);
+    int setCommand(char *iface, const char *fname, unsigned buflen=0);
 public:
     SoftapController();
     virtual ~SoftapController();
@@ -46,6 +46,7 @@
     bool isSoftapStarted();
     int setSoftap(int argc, char *argv[]);
     int fwReloadSoftap(int argc, char *argv[]);
+    int clientsSoftap(char **retbuf);
 };
 
 #endif
diff --git a/UsbController.cpp b/UsbController.cpp
deleted file mode 100644
index 16e5d6a..0000000
--- a/UsbController.cpp
+++ /dev/null
@@ -1,63 +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 <unistd.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#define LOG_TAG "UsbController"
-#include <cutils/log.h>
-
-#include "UsbController.h"
-
-
-UsbController::UsbController() {
-}
-
-UsbController::~UsbController() {
-}
-
-int UsbController::startRNDIS() {
-    LOGD("Usb RNDIS start");
-    return enableRNDIS(true);
-}
-
-int UsbController::stopRNDIS() {
-    LOGD("Usb RNDIS stop");
-    return enableRNDIS(false);
-}
-
-int UsbController::enableRNDIS(bool enable) {
-    char value[20];
-    int fd = open("/sys/class/usb_composite/rndis/enable", O_RDWR);
-    int count = snprintf(value, sizeof(value), "%d\n", (enable ? 1 : 0));
-    write(fd, value, count);
-    close(fd);
-    return 0;
-}
-
-bool UsbController::isRNDISStarted() {
-    char value=0;
-    int fd = open("/sys/class/usb_composite/rndis/enable", O_RDWR);
-    read(fd, &value, 1);
-    close(fd);
-    return (value == '1' ? true : false);
-}
diff --git a/UsbController.h b/UsbController.h
deleted file mode 100644
index 2de4bfa..0000000
--- a/UsbController.h
+++ /dev/null
@@ -1,37 +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.
- */
-
-#ifndef _USB_CONTROLLER_H
-#define _USB_CONTROLLER_H
-
-#include <linux/in.h>
-
-
-class UsbController {
-
-public:
-    UsbController();
-    virtual ~UsbController();
-
-    int startRNDIS();
-    int stopRNDIS();
-    bool isRNDISStarted();
-
-private:
-    int enableRNDIS(bool enable);
-};
-
-#endif