OSDN Git Service

Merge klp-dev-plus-aosp into stage-aosp-master
authorBill Yi <byi@google.com>
Tue, 29 Apr 2014 22:30:33 +0000 (15:30 -0700)
committerBill Yi <byi@google.com>
Tue, 29 Apr 2014 22:30:33 +0000 (15:30 -0700)
Change-Id: I1c46e9613eb7638531b6abffee43ffc94b116018

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

@@@ -1018,9 -1017,11 +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 2285b22,0000000..937347b
mode 100644,000000..100644
--- /dev/null
@@@ -1,117 -1,0 +1,120 @@@
-     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()
 +        : mDefaultNetId(NETID_UNSET),
 +          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 52ab7f4,0000000..dad011d
mode 100644,000000..100644
--- /dev/null
@@@ -1,78 -1,0 +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
  #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() {
@@@ -440,26 -461,32 +355,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) {
@@@ -476,11 -503,22 +392,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",
@@@ -29,8 -27,9 +29,7 @@@
  #define IFNAMSIZ 16
  #endif
  
 -static const int INTERFACES_TRACKED = 10;
  static const int BASE_TABLE_NUMBER = 60;
- static const int PROTECT_MARK = 0x1;
 -static int MAX_TABLE_NUMBER = BASE_TABLE_NUMBER + INTERFACES_TRACKED;
  static const char *EXEMPT_PRIO = "99";
  static const char *RULE_PRIO = "100";