OSDN Git Service

resolved conflicts for merge of 45d7b748 to klp-modular-dev-plus-aosp
authorPaul Jensen <pauljensen@google.com>
Thu, 3 Apr 2014 23:06:00 +0000 (19:06 -0400)
committerPaul Jensen <pauljensen@google.com>
Thu, 3 Apr 2014 23:06:00 +0000 (19:06 -0400)
Change-Id: I924e2c3c654501034dfa7429c0a54d0462fc1571

1  2 
CommandListener.cpp
NetworkController.cpp
NetworkController.h
ResolverController.cpp
SecondaryTableController.cpp
SecondaryTableController.h

@@@ -1017,11 -1018,9 +1017,11 @@@ int CommandListener::ResolverCmd::runCo
                      "Wrong number of arguments to resolver setifaceforuid", false);
              return 0;
          }
 -    } else if (!strcmp(argv[1], "clearifaceforuidrange")) { // resolver clearifaceforuid <l> <h>
 -        if (argc == 4) {
 -            rc = !sNetCtrl->setNetworkForUidRange(atoi(argv[2]), atoi(argv[3]), NETID_UNSET, false);
 +    } else if (!strcmp(argv[1], "clearifaceforuidrange")) {
 +        // resolver clearifaceforuid <if> <l> <h>
 +        if (argc == 5) {
-             rc = sResolverCtrl->clearDnsInterfaceForUidRange(argv[2], atoi(argv[3]),
-                     atoi(argv[4]));
++            unsigned netId = sNetCtrl->getNetworkId(argv[2]);
++            rc = !sNetCtrl->clearNetworkForUidRange(atoi(argv[3]), atoi(argv[4]), netId);
          } else {
              cli->sendMsg(ResponseCode::CommandSyntaxError,
                      "Wrong number of arguments to resolver clearifaceforuid", false);
index 0000000,a1f1535..398adb0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,115 +1,118 @@@
 -    if (uid_start > uid_end)
+ /*
+  * Copyright (C) 2014 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 <resolv_netid.h>
+ #define LOG_TAG "NetworkController"
+ #include <cutils/log.h>
+ #include "NetworkController.h"
+ // Mark 1 is reserved for SecondaryTableController::PROTECT_MARK.
+ NetworkController::NetworkController() : mNextFreeNetId(10) {}
+ void NetworkController::clearNetworkPreference() {
+     android::RWLock::AutoWLock lock(mRWLock);
+     mUidMap.clear();
+     mPidMap.clear();
+ }
+ unsigned NetworkController::getDefaultNetwork() const {
+     return mDefaultNetId;
+ }
+ void NetworkController::setDefaultNetwork(unsigned netId) {
+     android::RWLock::AutoWLock lock(mRWLock);
+     mDefaultNetId = netId;
+ }
+ void NetworkController::setNetworkForPid(int pid, unsigned netId) {
+     android::RWLock::AutoWLock lock(mRWLock);
+     if (netId == 0) {
+         mPidMap.erase(pid);
+     } else {
+         mPidMap[pid] = netId;
+     }
+ }
+ bool NetworkController::setNetworkForUidRange(int uid_start, int uid_end, unsigned netId,
+         bool forward_dns) {
+     android::RWLock::AutoWLock lock(mRWLock);
 -        if (it->uid_start > uid_end || uid_start > it->uid_end)
++    if (uid_start > uid_end || netId == NETID_UNSET)
+         return false;
+     for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
 -        /* Overlapping or identical range. */
 -        if (it->uid_start != uid_start || it->uid_end != uid_end) {
 -            ALOGE("Overlapping but not identical uid range detected.");
 -            return false;
 -        }
 -
 -        if (netId == NETID_UNSET) {
 -            mUidMap.erase(it);
 -        } else {
 -            it->netId = netId;
 -            it->forward_dns = forward_dns;
 -        }
++        if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
+             continue;
 -    mUidMap.push_back(UidEntry(uid_start, uid_end, netId, forward_dns));
++        it->forward_dns = forward_dns;
+         return true;
+     }
++    mUidMap.push_front(UidEntry(uid_start, uid_end, netId, forward_dns));
+     return true;
+ }
++bool NetworkController::clearNetworkForUidRange(int uid_start, int uid_end, unsigned netId) {
++    android::RWLock::AutoWLock lock(mRWLock);
++    if (uid_start > uid_end || netId == NETID_UNSET)
++        return false;
++
++    for (std::list<UidEntry>::iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
++        if (it->uid_start != uid_start || it->uid_end != uid_end || it->netId != netId)
++            continue;
++        mUidMap.erase(it);
++        return true;
++    }
++    return false;
++}
++
+ unsigned NetworkController::getNetwork(int uid, unsigned requested_netId, int pid,
+         bool for_dns) const {
+     android::RWLock::AutoRLock lock(mRWLock);
+     for (std::list<UidEntry>::const_iterator it = mUidMap.begin(); it != mUidMap.end(); ++it) {
+         if (uid < it->uid_start || it->uid_end < uid)
+             continue;
+         if (for_dns && !it->forward_dns)
+             break;
+         return it->netId;
+     }
+     if (requested_netId != NETID_UNSET)
+         return requested_netId;
+     if (pid != PID_UNSPECIFIED) {
+         std::map<int, unsigned>::const_iterator it = mPidMap.find(pid);
+         if (it != mPidMap.end())
+             return it->second;
+     }
+     return mDefaultNetId;
+ }
+ unsigned NetworkController::getNetworkId(const char* interface) {
+     std::map<std::string, unsigned>::const_iterator it = mIfaceNetidMap.find(interface);
+     if (it != mIfaceNetidMap.end())
+         return it->second;
+     unsigned netId = mNextFreeNetId++;
+     mIfaceNetidMap[interface] = netId;
+     return netId;
+ }
+ NetworkController::UidEntry::UidEntry(
+     int start, int end, unsigned netId, bool forward_dns)
+       : uid_start(start),
+         uid_end(end),
+         netId(netId),
+         forward_dns(forward_dns) {
+ }
index 0000000,52ab7f4..dad011d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,78 +1,77 @@@
 -    // Returns false if a partially overlapping range exists.
 -    // Specify NETID_UNSET for netId to clear a mapping.
+ /*
+  * Copyright (C) 2014 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 _NETD_NETWORKCONTROLLER_H
+ #define _NETD_NETWORKCONTROLLER_H
+ #include <list>
+ #include <map>
+ #include <string>
+ #include <stddef.h>
+ #include <stdint.h>
+ #include <utils/RWLock.h>
+ /*
+  * Keeps track of default, per-pid, and per-uid-range network selection, as
+  * well as the mark associated with each network. Networks are identified
+  * by netid. In all set* commands netid == 0 means "unspecified" and is
+  * equivalent to clearing the mapping.
+  */
+ class NetworkController {
+ public:
+     enum {
+         // For use with getNetwork().
+         PID_UNSPECIFIED = 0,
+     };
+     NetworkController();
+     void clearNetworkPreference();
+     unsigned getDefaultNetwork() const;
+     void setDefaultNetwork(unsigned netId);
+     void setNetworkForPid(int pid, unsigned netId);
+     bool setNetworkForUidRange(int uid_start, int uid_end, unsigned netId, bool forward_dns);
++    bool clearNetworkForUidRange(int uid_start, int uid_end, unsigned netId);
+     // Order of preference: UID-specific, requested_netId, PID-specific, default.
+     // Specify NETID_UNSET for requested_netId if the default network is preferred.
+     // Specify PID_UNSPECIFIED for pid to ignore PID-specific overrides.
+     // for_dns indicates if we're querrying the netId for a DNS request.  This avoids sending DNS
+     // requests to VPNs without DNS servers.
+     unsigned getNetwork(int uid, unsigned requested_netId, int pid, bool for_dns) const;
+     unsigned getNetworkId(const char* interface);
+ private:
+     struct UidEntry {
+         int uid_start;
+         int uid_end;
+         unsigned netId;
+         bool forward_dns;
+         UidEntry(int uid_start, int uid_end, unsigned netId, bool forward_dns);
+     };
+     mutable android::RWLock mRWLock;
+     std::list<UidEntry> mUidMap;
+     std::map<int, unsigned> mPidMap;
+     unsigned mDefaultNetId;
+     std::map<std::string, unsigned> mIfaceNetidMap;
+     unsigned mNextFreeNetId;
+ };
+ #endif
Simple merge
  #include "SecondaryTableController.h"
  
  const char* SecondaryTableController::LOCAL_MANGLE_OUTPUT = "st_mangle_OUTPUT";
 -const char* SecondaryTableController::LOCAL_MANGLE_EXEMPT = "st_mangle_EXEMPT";
 -const char* SecondaryTableController::LOCAL_MANGLE_IFACE_FORMAT = "st_mangle_%s_OUTPUT";
 +const char* SecondaryTableController::LOCAL_MANGLE_POSTROUTING = "st_mangle_POSTROUTING";
  const char* SecondaryTableController::LOCAL_NAT_POSTROUTING = "st_nat_POSTROUTING";
 -const char* SecondaryTableController::LOCAL_FILTER_OUTPUT = "st_filter_OUTPUT";
  
- SecondaryTableController::SecondaryTableController(UidMarkMap *map) : mUidMarkMap(map) {
-     int i;
-     for (i=0; i < INTERFACES_TRACKED; i++) {
-         mInterfaceTable[i][0] = 0;
-         // TODO - use a hashtable or other prebuilt container class
-         mInterfaceRuleCount[i] = 0;
-     }
+ SecondaryTableController::SecondaryTableController(NetworkController* controller) :
+         mNetCtrl(controller) {
  }
  
  SecondaryTableController::~SecondaryTableController() {
@@@ -314,39 -246,10 +237,41 @@@ int SecondaryTableController::setFwmark
          return -1;
      }
  
-     snprintf(mark_str, sizeof(mark_str), "%d", mark);
+     int ret;
+     char mark_str[11];
+     snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
 -    //add the catch all route to the tun. Route rules will make sure the right packets hit the table
 +    // Flush any marked routes we added
 +    if (!add) {
 +        // iproute2 rule del will delete anything that matches, but only one rule at a time.
 +        // So clearing the rules requires a bunch of calls.
 +        // ip rule del will fail once there are no remaining rules that match.
 +        const char *v4_cmd[] = {
 +            IP_PATH,
 +            "-4",
 +            "rule",
 +            "del",
 +            "fwmark",
 +            mark_str,
 +            "table",
 +            mark_str
 +        };
 +        while(!runCmd(ARRAY_SIZE(v4_cmd), v4_cmd)) {}
 +
 +        const char *v6_cmd[] = {
 +            IP_PATH,
 +            "-6",
 +            "rule",
 +            "del",
 +            "fwmark",
 +            mark_str,
 +            "table",
 +            mark_str
 +        };
 +        while(!runCmd(ARRAY_SIZE(v6_cmd), v6_cmd)) {}
 +    }
 +    // Add a route to the table to send all traffic to iface.
 +    // We only need a default route because this table is only selected if a packet matches an
 +    // IP rule that checks both the route and the mark.
      const char *route_cmd[] = {
          IP_PATH,
          "route",
@@@ -461,32 -440,26 +386,27 @@@ int SecondaryTableController::removeFwm
  
  int SecondaryTableController::setFwmarkRoute(const char* iface, const char *dest, int prefix,
                                               bool add) {
-     int tableIndex = findTableNumber(iface);
-     if (tableIndex == -1) {
-         errno = EINVAL;
-         return -1;
-     }
-     int mark = tableIndex + BASE_TABLE_NUMBER;
+     unsigned netId = mNetCtrl->getNetworkId(iface);
      char mark_str[11] = {0};
 -    char chain_str[IFNAMSIZ + 18];
      char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
  
-     snprintf(mark_str, sizeof(mark_str), "%d", mark);
+     snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
 -    snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
      snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
 -    return execIptables(getIptablesTarget(dest),
 -            "-t",
 -            "mangle",
 -            add ? "-A" : "-D",
 -            chain_str,
 -            "-d",
 -            dest_str,
 -            "-j",
 -            "MARK",
 -            "--set-mark",
 -            mark_str,
 -            NULL);
 +    const char *rule_cmd[] = {
 +        IP_PATH,
 +        getVersion(dest_str),
 +        "rule",
 +        add ? "add" : "del",
 +        "prio",
 +        RULE_PRIO,
 +        "to",
 +        dest_str,
 +        "fwmark",
 +        mark_str,
 +        "table",
 +        mark_str
 +    };
 +    return runCmd(ARRAY_SIZE(rule_cmd), rule_cmd);
  }
  
  int SecondaryTableController::addUidRule(const char *iface, int uid_start, int uid_end) {
@@@ -503,22 -476,11 +423,11 @@@ int SecondaryTableController::setUidRul
          errno = EINVAL;
          return -1;
      }
-     int mark = tableIndex + BASE_TABLE_NUMBER;
-     if (add) {
-         if (!mUidMarkMap->add(uid_start, uid_end, mark)) {
-             errno = EINVAL;
-             return -1;
-         }
-     } else {
-         if (!mUidMarkMap->remove(uid_start, uid_end, mark)) {
-             errno = EINVAL;
-             return -1;
-         }
-     }
      char uid_str[24] = {0};
 -    char chain_str[IFNAMSIZ + 18];
      snprintf(uid_str, sizeof(uid_str), "%d-%d", uid_start, uid_end);
 -    snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
 +    char mark_str[11] = {0};
-     snprintf(mark_str, sizeof(mark_str), "%d", mark);
++    snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
      return execIptables(V4V6,
              "-t",
              "mangle",
@@@ -27,9 -29,8 +29,7 @@@
  #define IFNAMSIZ 16
  #endif
  
- static const int INTERFACES_TRACKED = 10;
  static const int BASE_TABLE_NUMBER = 60;
- static int MAX_TABLE_NUMBER = BASE_TABLE_NUMBER + INTERFACES_TRACKED;
 -static const int PROTECT_MARK = 0x1;
  static const char *EXEMPT_PRIO = "99";
  static const char *RULE_PRIO = "100";