diff options
author | Chad Brubaker <cbrubaker@google.com> | 2013-06-21 15:26:35 -0700 |
---|---|---|
committer | Chad Brubaker <cbrubaker@google.com> | 2013-06-26 15:21:46 -0700 |
commit | d2617936acc15567fc5111bbdb4dde20845c3cba (patch) | |
tree | 454bfd4fc71de51022ea364d6c5ee3d7a68b9a70 | |
parent | eb648acc30c3b04823c8ee533b12ae56d772ce47 (diff) | |
download | netd-d2617936acc15567fc5111bbdb4dde20845c3cba.tar.gz |
Add netd support for uid based routing for DNS
DNSProxyListener now supports bionic changes for marking DNS requests
for routing DNS requests with the uid routing rules
Change-Id: Iac9aa1bb14834be6da5e512405f23c6a72dc71ed
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | CommandListener.cpp | 4 | ||||
-rw-r--r-- | CommandListener.h | 3 | ||||
-rw-r--r-- | DnsProxyListener.cpp | 52 | ||||
-rw-r--r-- | DnsProxyListener.h | 28 | ||||
-rw-r--r-- | SecondaryTableController.cpp | 21 | ||||
-rw-r--r-- | SecondaryTableController.h | 5 | ||||
-rw-r--r-- | UidMarkMap.cpp | 67 | ||||
-rw-r--r-- | UidMarkMap.h | 42 | ||||
-rw-r--r-- | main.cpp | 6 |
10 files changed, 193 insertions, 36 deletions
@@ -22,6 +22,7 @@ LOCAL_SRC_FILES:= \ SoftapController.cpp \ TetherController.cpp \ oem_iptables_hook.cpp \ + UidMarkMap.cpp \ main.cpp \ diff --git a/CommandListener.cpp b/CommandListener.cpp index 026797f2..a480d671 100644 --- a/CommandListener.cpp +++ b/CommandListener.cpp @@ -128,7 +128,7 @@ static void createChildChains(IptablesTarget target, const char* table, const ch } while (*(++childChain) != NULL); } -CommandListener::CommandListener() : +CommandListener::CommandListener(UidMarkMap *map) : FrameworkListener("netd", true) { registerCmd(new InterfaceCmd()); registerCmd(new IpFwdCmd()); @@ -144,7 +144,7 @@ CommandListener::CommandListener() : registerCmd(new ClatdCmd()); if (!sSecondaryTableCtrl) - sSecondaryTableCtrl = new SecondaryTableController(); + sSecondaryTableCtrl = new SecondaryTableController(map); if (!sTetherCtrl) sTetherCtrl = new TetherController(); if (!sNatCtrl) diff --git a/CommandListener.h b/CommandListener.h index 1db81f81..23b8dd1f 100644 --- a/CommandListener.h +++ b/CommandListener.h @@ -31,6 +31,7 @@ #include "SecondaryTableController.h" #include "FirewallController.h" #include "ClatdController.h" +#include "UidMarkMap.h" class CommandListener : public FrameworkListener { static TetherController *sTetherCtrl; @@ -46,7 +47,7 @@ class CommandListener : public FrameworkListener { static ClatdController *sClatdCtrl; public: - CommandListener(); + CommandListener(UidMarkMap *map); virtual ~CommandListener() {} private: diff --git a/DnsProxyListener.cpp b/DnsProxyListener.cpp index 18fa2676..a025828f 100644 --- a/DnsProxyListener.cpp +++ b/DnsProxyListener.cpp @@ -35,14 +35,16 @@ #include <cutils/log.h> #include <sysutils/SocketClient.h> +#include "NetdConstants.h" #include "DnsProxyListener.h" #include "ResponseCode.h" -DnsProxyListener::DnsProxyListener() : +DnsProxyListener::DnsProxyListener(UidMarkMap *map) : FrameworkListener("dnsproxyd") { - registerCmd(new GetAddrInfoCmd()); - registerCmd(new GetHostByAddrCmd()); - registerCmd(new GetHostByNameCmd()); + registerCmd(new GetAddrInfoCmd(map)); + registerCmd(new GetHostByAddrCmd(map)); + registerCmd(new GetHostByNameCmd(map)); + mUidMarkMap = map; } DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient *c, @@ -51,14 +53,16 @@ DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient *c, struct addrinfo* hints, char* iface, pid_t pid, - uid_t uid) + uid_t uid, + int mark) : mClient(c), mHost(host), mService(service), mHints(hints), mIface(iface), mPid(pid), - mUid(uid) { + mUid(uid), + mMark(mark) { } DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() { @@ -133,7 +137,7 @@ void DnsProxyListener::GetAddrInfoHandler::run() { struct addrinfo* result = NULL; uint32_t rv = android_getaddrinfoforiface(mHost, mService, mHints, mIface ? mIface : tmp, - &result); + mMark, &result); if (rv) { // getaddrinfo failed mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, &rv, sizeof(rv)); @@ -159,8 +163,9 @@ void DnsProxyListener::GetAddrInfoHandler::run() { mClient->decRef(); } -DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd() : +DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd(UidMarkMap *uidMarkMap) : NetdCommand("getaddrinfo") { + mUidMarkMap = uidMarkMap; } int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, @@ -227,7 +232,8 @@ int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, cli->incRef(); DnsProxyListener::GetAddrInfoHandler* handler = - new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, iface, pid, uid); + new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, iface, pid, uid, + mUidMarkMap->getMark(uid)); handler->start(); return 0; @@ -236,8 +242,9 @@ int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, /******************************************************* * GetHostByName * *******************************************************/ -DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd() : +DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd(UidMarkMap *uidMarkMap) : NetdCommand("gethostbyname") { + mUidMarkMap = uidMarkMap; } int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli, @@ -276,7 +283,8 @@ int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli, cli->incRef(); DnsProxyListener::GetHostByNameHandler* handler = - new DnsProxyListener::GetHostByNameHandler(cli, pid, uid, iface, name, af); + new DnsProxyListener::GetHostByNameHandler(cli, pid, uid, iface, name, af, + mUidMarkMap->getMark(uid)); handler->start(); return 0; @@ -287,13 +295,15 @@ DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c, uid_t uid, char* iface, char* name, - int af) + int af, + int mark) : mClient(c), mPid(pid), mUid(uid), mIface(iface), mName(name), - mAf(af) { + mAf(af), + mMark(mark) { } DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() { @@ -330,7 +340,7 @@ void DnsProxyListener::GetHostByNameHandler::run() { struct hostent* hp; - hp = android_gethostbynameforiface(mName, mAf, mIface ? mIface : iface); + hp = android_gethostbynameforiface(mName, mAf, mIface ? mIface : iface, mMark); if (DBG) { ALOGD("GetHostByNameHandler::run gethostbyname errno: %s hp->h_name = %s, name_len = %d\n", @@ -357,8 +367,9 @@ void DnsProxyListener::GetHostByNameHandler::run() { /******************************************************* * GetHostByAddr * *******************************************************/ -DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd() : +DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd(UidMarkMap *uidMarkMap) : NetdCommand("gethostbyaddr") { + mUidMarkMap = uidMarkMap; } int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli, @@ -405,7 +416,8 @@ int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli, cli->incRef(); DnsProxyListener::GetHostByAddrHandler* handler = - new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily, iface, pid, uid); + new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily, iface, pid, + uid, mUidMarkMap->getMark(uid)); handler->start(); return 0; @@ -417,14 +429,16 @@ DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c, int addressFamily, char* iface, pid_t pid, - uid_t uid) + uid_t uid, + int mark) : mClient(c), mAddress(address), mAddressLen(addressLen), mAddressFamily(addressFamily), mIface(iface), mPid(pid), - mUid(uid) { + mUid(uid), + mMark(mark) { } DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() { @@ -462,7 +476,7 @@ void DnsProxyListener::GetHostByAddrHandler::run() { // NOTE gethostbyaddr should take a void* but bionic thinks it should be char* hp = android_gethostbyaddrforiface((char*)mAddress, mAddressLen, mAddressFamily, - mIface ? mIface : tmp); + mIface ? mIface : tmp, mMark); if (DBG) { ALOGD("GetHostByAddrHandler::run gethostbyaddr errno: %s hp->h_name = %s, name_len = %d\n", diff --git a/DnsProxyListener.h b/DnsProxyListener.h index 758ca76d..2061d71d 100644 --- a/DnsProxyListener.h +++ b/DnsProxyListener.h @@ -20,18 +20,22 @@ #include <sysutils/FrameworkListener.h> #include "NetdCommand.h" +#include "UidMarkMap.h" class DnsProxyListener : public FrameworkListener { public: - DnsProxyListener(); + DnsProxyListener(UidMarkMap *map); virtual ~DnsProxyListener() {} private: + UidMarkMap *mUidMarkMap; class GetAddrInfoCmd : public NetdCommand { public: - GetAddrInfoCmd(); + GetAddrInfoCmd(UidMarkMap *uidMarkMap); virtual ~GetAddrInfoCmd() {} int runCommand(SocketClient *c, int argc, char** argv); + private: + UidMarkMap *mUidMarkMap; }; class GetAddrInfoHandler { @@ -43,7 +47,8 @@ private: struct addrinfo* hints, char* iface, pid_t pid, - uid_t uid); + uid_t uid, + int mark); ~GetAddrInfoHandler(); static void* threadStart(void* handler); @@ -58,14 +63,17 @@ private: char* mIface; // owned pid_t mPid; uid_t mUid; + int mMark; }; /* ------ gethostbyname ------*/ class GetHostByNameCmd : public NetdCommand { public: - GetHostByNameCmd(); + GetHostByNameCmd(UidMarkMap *uidMarkMap); virtual ~GetHostByNameCmd() {} int runCommand(SocketClient *c, int argc, char** argv); + private: + UidMarkMap *mUidMarkMap; }; class GetHostByNameHandler { @@ -75,7 +83,8 @@ private: uid_t uid, char *iface, char *name, - int af); + int af, + int mark); ~GetHostByNameHandler(); static void* threadStart(void* handler); void start(); @@ -87,14 +96,17 @@ private: char* mIface; // owned char* mName; // owned int mAf; + int mMark; }; /* ------ gethostbyaddr ------*/ class GetHostByAddrCmd : public NetdCommand { public: - GetHostByAddrCmd(); + GetHostByAddrCmd(UidMarkMap *uidMarkMap); virtual ~GetHostByAddrCmd() {} int runCommand(SocketClient *c, int argc, char** argv); + private: + UidMarkMap *mUidMarkMap; }; class GetHostByAddrHandler { @@ -105,7 +117,8 @@ private: int addressFamily, char* iface, pid_t pid, - uid_t uid); + uid_t uid, + int mark); ~GetHostByAddrHandler(); static void* threadStart(void* handler); @@ -120,6 +133,7 @@ private: char* mIface; // owned pid_t mPid; uid_t mUid; + int mMark; }; }; diff --git a/SecondaryTableController.cpp b/SecondaryTableController.cpp index 222a0e04..89a307b0 100644 --- a/SecondaryTableController.cpp +++ b/SecondaryTableController.cpp @@ -39,7 +39,7 @@ const char* SecondaryTableController::LOCAL_MANGLE_OUTPUT = "st_mangle_OUTPUT"; const char* SecondaryTableController::LOCAL_NAT_POSTROUTING = "st_nat_POSTROUTING"; -SecondaryTableController::SecondaryTableController() { +SecondaryTableController::SecondaryTableController(UidMarkMap *map) : mUidMarkMap(map) { int i; for (i=0; i < INTERFACES_TRACKED; i++) { mInterfaceTable[i][0] = 0; @@ -301,10 +301,23 @@ int SecondaryTableController::removeUidRule(const char *iface, int uid_start, in int SecondaryTableController::setUidRule(const char *iface, int uid_start, int uid_end, bool add) { int tableIndex = findTableNumber(iface); if (tableIndex == -1) { + errno = EINVAL; return -1; } - char tableIndex_str[11] = {0}; - snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex + BASE_TABLE_NUMBER); + 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 mark_str[11] = {0}; + snprintf(mark_str, sizeof(mark_str), "%d", mark); char uid_str[24] = {0}; snprintf(uid_str, sizeof(uid_str), "%d-%d", uid_start, uid_end); return execIptables(V4V6, @@ -319,7 +332,7 @@ int SecondaryTableController::setUidRule(const char *iface, int uid_start, int u "-j", "MARK", "--set-mark", - tableIndex_str, + mark_str, NULL); } diff --git a/SecondaryTableController.h b/SecondaryTableController.h index 3941ba12..48baa9f8 100644 --- a/SecondaryTableController.h +++ b/SecondaryTableController.h @@ -20,6 +20,7 @@ #include <sysutils/FrameworkListener.h> #include <net/if.h> +#include "UidMarkMap.h" #ifndef IFNAMSIZ #define IFNAMSIZ 16 @@ -32,7 +33,7 @@ static int MAX_TABLE_NUMBER = BASE_TABLE_NUMBER + INTERFACES_TRACKED; class SecondaryTableController { public: - SecondaryTableController(); + SecondaryTableController(UidMarkMap *map); virtual ~SecondaryTableController(); int addRoute(SocketClient *cli, char *iface, char *dest, int prefixLen, char *gateway); @@ -50,6 +51,8 @@ public: private: + UidMarkMap *mUidMarkMap; + int setUidRule(const char* iface, int uid_start, int uid_end, bool add); int setFwmarkRule(const char *iface, bool add); int modifyRoute(SocketClient *cli, const char *action, char *iface, char *dest, int prefix, diff --git a/UidMarkMap.cpp b/UidMarkMap.cpp new file mode 100644 index 00000000..34764cf6 --- /dev/null +++ b/UidMarkMap.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2013 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 "UidMarkMap.h" + +UidMarkMap::UidMarkEntry::UidMarkEntry(int start, int end, int new_mark) : + uid_start(start), + uid_end(end), + mark(new_mark) { +}; + +bool UidMarkMap::add(int uid_start, int uid_end, int mark) { + android::RWLock::AutoWLock lock(mRWLock); + if (uid_start > uid_end) { + return false; + } + android::netd::List<UidMarkEntry*>::iterator it; + for (it = mMap.begin(); it != mMap.end(); it++) { + UidMarkEntry *entry = *it; + if (entry->uid_start <= uid_end && uid_start <= entry->uid_end) { + return false; + } + } + + UidMarkEntry *e = new UidMarkEntry(uid_start, uid_end, mark); + mMap.push_back(e); + return true; +}; + +bool UidMarkMap::remove(int uid_start, int uid_end, int mark) { + android::RWLock::AutoWLock lock(mRWLock); + android::netd::List<UidMarkEntry*>::iterator it; + for (it = mMap.begin(); it != mMap.end(); it++) { + UidMarkEntry *entry = *it; + if (entry->uid_start == uid_start && entry->uid_end == uid_end && entry->mark == mark) { + mMap.erase(it); + delete entry; + return true; + } + } + return false; +}; + +int UidMarkMap::getMark(int uid) { + android::RWLock::AutoRLock lock(mRWLock); + android::netd::List<UidMarkEntry*>::iterator it; + for (it = mMap.begin(); it != mMap.end(); it++) { + UidMarkEntry *entry = *it; + if (entry->uid_start <= uid && entry->uid_end >= uid) { + return entry->mark; + } + } + return -1; +}; diff --git a/UidMarkMap.h b/UidMarkMap.h new file mode 100644 index 00000000..52b9e835 --- /dev/null +++ b/UidMarkMap.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 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_UIDMARKMAP_H +#define _NETD_UIDMARKMAP_H + +#include <stddef.h> +#include <stdint.h> +#include <List.h> +#include <utils/RWLock.h> + +class UidMarkMap { +public: + bool add(int uid_start, int uid_end, int mark); + bool remove(int uid_start, int uid_end, int mark); + int getMark(int uid); + +private: + struct UidMarkEntry { + int uid_start; + int uid_end; + int mark; + UidMarkEntry(int uid_start, int uid_end, int mark); + }; + + android::RWLock mRWLock; + android::netd::List<UidMarkEntry*> mMap; +}; +#endif @@ -34,6 +34,7 @@ #include "NetlinkManager.h" #include "DnsProxyListener.h" #include "MDnsSdListener.h" +#include "UidMarkMap.h" static void coldboot(const char *path); static void sigchld_handler(int sig); @@ -56,8 +57,9 @@ int main() { exit(1); }; + UidMarkMap *rangeMap = new UidMarkMap(); - cl = new CommandListener(); + cl = new CommandListener(rangeMap); nm->setBroadcaster((SocketListener *) cl); if (nm->start()) { @@ -68,7 +70,7 @@ int main() { // Set local DNS mode, to prevent bionic from proxying // back to this service, recursively. setenv("ANDROID_DNS_MODE", "local", 1); - dpl = new DnsProxyListener(); + dpl = new DnsProxyListener(rangeMap); if (dpl->startListener()) { ALOGE("Unable to start DnsProxyListener (%s)", strerror(errno)); exit(1); |