summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Brubaker <cbrubaker@google.com>2013-06-21 15:26:35 -0700
committerChad Brubaker <cbrubaker@google.com>2013-06-26 15:21:46 -0700
commitd2617936acc15567fc5111bbdb4dde20845c3cba (patch)
tree454bfd4fc71de51022ea364d6c5ee3d7a68b9a70
parenteb648acc30c3b04823c8ee533b12ae56d772ce47 (diff)
downloadnetd-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.mk1
-rw-r--r--CommandListener.cpp4
-rw-r--r--CommandListener.h3
-rw-r--r--DnsProxyListener.cpp52
-rw-r--r--DnsProxyListener.h28
-rw-r--r--SecondaryTableController.cpp21
-rw-r--r--SecondaryTableController.h5
-rw-r--r--UidMarkMap.cpp67
-rw-r--r--UidMarkMap.h42
-rw-r--r--main.cpp6
10 files changed, 193 insertions, 36 deletions
diff --git a/Android.mk b/Android.mk
index f49a7f96..da4a7adb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -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
diff --git a/main.cpp b/main.cpp
index b466e423..104ebe13 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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);