SoftapController.cpp \
TetherController.cpp \
oem_iptables_hook.cpp \
+ UidMarkMap.cpp \
main.cpp \
} while (*(++childChain) != NULL);
}
-CommandListener::CommandListener() :
+CommandListener::CommandListener(UidMarkMap *map) :
FrameworkListener("netd", true) {
registerCmd(new InterfaceCmd());
registerCmd(new IpFwdCmd());
registerCmd(new ClatdCmd());
if (!sSecondaryTableCtrl)
- sSecondaryTableCtrl = new SecondaryTableController();
+ sSecondaryTableCtrl = new SecondaryTableController(map);
if (!sTetherCtrl)
sTetherCtrl = new TetherController();
if (!sNatCtrl)
#include "SecondaryTableController.h"
#include "FirewallController.h"
#include "ClatdController.h"
+#include "UidMarkMap.h"
class CommandListener : public FrameworkListener {
static TetherController *sTetherCtrl;
static ClatdController *sClatdCtrl;
public:
- CommandListener();
+ CommandListener(UidMarkMap *map);
virtual ~CommandListener() {}
private:
#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,
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() {
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));
mClient->decRef();
}
-DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd() :
+DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd(UidMarkMap *uidMarkMap) :
NetdCommand("getaddrinfo") {
+ mUidMarkMap = uidMarkMap;
}
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;
/*******************************************************
* GetHostByName *
*******************************************************/
-DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd() :
+DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd(UidMarkMap *uidMarkMap) :
NetdCommand("gethostbyname") {
+ mUidMarkMap = uidMarkMap;
}
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;
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() {
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",
/*******************************************************
* GetHostByAddr *
*******************************************************/
-DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd() :
+DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd(UidMarkMap *uidMarkMap) :
NetdCommand("gethostbyaddr") {
+ mUidMarkMap = uidMarkMap;
}
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;
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() {
// 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",
#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 {
struct addrinfo* hints,
char* iface,
pid_t pid,
- uid_t uid);
+ uid_t uid,
+ int mark);
~GetAddrInfoHandler();
static void* threadStart(void* handler);
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 {
uid_t uid,
char *iface,
char *name,
- int af);
+ int af,
+ int mark);
~GetHostByNameHandler();
static void* threadStart(void* handler);
void start();
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 {
int addressFamily,
char* iface,
pid_t pid,
- uid_t uid);
+ uid_t uid,
+ int mark);
~GetHostByAddrHandler();
static void* threadStart(void* handler);
char* mIface; // owned
pid_t mPid;
uid_t mUid;
+ int mMark;
};
};
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;
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,
"-j",
"MARK",
"--set-mark",
- tableIndex_str,
+ mark_str,
NULL);
}
#include <sysutils/FrameworkListener.h>
#include <net/if.h>
+#include "UidMarkMap.h"
#ifndef IFNAMSIZ
#define IFNAMSIZ 16
class SecondaryTableController {
public:
- SecondaryTableController();
+ SecondaryTableController(UidMarkMap *map);
virtual ~SecondaryTableController();
int addRoute(SocketClient *cli, char *iface, char *dest, int prefixLen, char *gateway);
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,
--- /dev/null
+/*
+ * 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;
+};
--- /dev/null
+/*
+ * 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
#include "NetlinkManager.h"
#include "DnsProxyListener.h"
#include "MDnsSdListener.h"
+#include "UidMarkMap.h"
static void coldboot(const char *path);
static void sigchld_handler(int sig);
exit(1);
};
+ UidMarkMap *rangeMap = new UidMarkMap();
- cl = new CommandListener();
+ cl = new CommandListener(rangeMap);
nm->setBroadcaster((SocketListener *) cl);
if (nm->start()) {
// 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);