#include "DnsProxyListener.h"
#include "NetdConstants.h"
#include "NetworkController.h"
-#include "PermissionsController.h"
#include "ResponseCode.h"
-DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl,
- const PermissionsController* permCtrl) :
- FrameworkListener("dnsproxyd"),
- mNetCtrl(netCtrl),
- mPermCtrl(permCtrl) {
+DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl) :
+ FrameworkListener("dnsproxyd"), mNetCtrl(netCtrl) {
registerCmd(new GetAddrInfoCmd(this));
registerCmd(new GetHostByAddrCmd(this));
registerCmd(new GetHostByNameCmd(this));
}
-uint32_t DnsProxyListener::calcMark(SocketClient *c, unsigned netId) const {
- Fwmark fwmark;
- fwmark.netId = netId;
- // If netd's UID is forced into a VPN that isn't the intended network,
- // use VPN protect bit to force it into the desired network.
- fwmark.protectedFromVpn = mNetCtrl->getNetwork(getuid(), netId, true) != netId;
- fwmark.permission = mPermCtrl->getPermissionForUser(c->getUid());
- return fwmark.intValue;
-}
-
-DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient *c,
- char* host,
- char* service,
- struct addrinfo* hints,
- unsigned netId,
- uint32_t mark)
+DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(
+ SocketClient *c, char* host, char* service, struct addrinfo* hints,
+ const struct android_net_context& netcontext)
: mClient(c),
mHost(host),
mService(service),
mHints(hints),
- mNetId(netId),
- mMark(mark) {
+ mNetContext(netcontext) {
}
DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
return NULL;
}
+static bool sendBE32(SocketClient* c, uint32_t data) {
+ uint32_t be_data = htonl(data);
+ return c->sendData(&be_data, sizeof(be_data)) == 0;
+}
+
// Sends 4 bytes of big-endian length, followed by the data.
// Returns true on success.
-static bool sendLenAndData(SocketClient *c, const int len, const void* data) {
- uint32_t len_be = htonl(len);
- return c->sendData(&len_be, 4) == 0 &&
- (len == 0 || c->sendData(data, len) == 0);
+static bool sendLenAndData(SocketClient* c, const int len, const void* data) {
+ return sendBE32(c, len) && (len == 0 || c->sendData(data, len) == 0);
}
// Returns true on success
return success;
}
+static bool sendaddrinfo(SocketClient* c, struct addrinfo* ai) {
+ // struct addrinfo {
+ // int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+ // int ai_family; /* PF_xxx */
+ // int ai_socktype; /* SOCK_xxx */
+ // int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ // socklen_t ai_addrlen; /* length of ai_addr */
+ // char *ai_canonname; /* canonical name for hostname */
+ // struct sockaddr *ai_addr; /* binary address */
+ // struct addrinfo *ai_next; /* next structure in linked list */
+ // };
+
+ // Write the struct piece by piece because we might be a 64-bit netd
+ // talking to a 32-bit process.
+ bool success =
+ sendBE32(c, ai->ai_flags) &&
+ sendBE32(c, ai->ai_family) &&
+ sendBE32(c, ai->ai_socktype) &&
+ sendBE32(c, ai->ai_protocol);
+ if (!success) {
+ return false;
+ }
+
+ // ai_addrlen and ai_addr.
+ if (!sendLenAndData(c, ai->ai_addrlen, ai->ai_addr)) {
+ return false;
+ }
+
+ // strlen(ai_canonname) and ai_canonname.
+ if (!sendLenAndData(c, ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0, ai->ai_canonname)) {
+ return false;
+ }
+
+ return true;
+}
+
void DnsProxyListener::GetAddrInfoHandler::run() {
if (DBG) {
- ALOGD("GetAddrInfoHandler, now for %s / %s / %u / %u", mHost, mService, mNetId, mMark);
+ ALOGD("GetAddrInfoHandler, now for %s / %s / {%u,%u,%u,%u,%u}", mHost, mService,
+ mNetContext.app_netid, mNetContext.app_mark,
+ mNetContext.dns_netid, mNetContext.dns_mark,
+ mNetContext.uid);
}
struct addrinfo* result = NULL;
- uint32_t rv = android_getaddrinfofornet(mHost, mService, mHints, mNetId, mMark, &result);
+ uint32_t rv = android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext, &result);
if (rv) {
// getaddrinfo failed
mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, &rv, sizeof(rv));
bool success = !mClient->sendCode(ResponseCode::DnsProxyQueryResult);
struct addrinfo* ai = result;
while (ai && success) {
- success = sendLenAndData(mClient, sizeof(struct addrinfo), ai)
- && sendLenAndData(mClient, ai->ai_addrlen, ai->ai_addr)
- && sendLenAndData(mClient,
- ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0,
- ai->ai_canonname);
+ success = sendBE32(mClient, 1) && sendaddrinfo(mClient, ai);
ai = ai->ai_next;
}
- success = success && sendLenAndData(mClient, 0, "");
+ success = success && sendBE32(mClient, 0);
if (!success) {
ALOGW("Error writing DNS result to client");
}
unsigned netId = strtoul(argv[7], NULL, 10);
uid_t uid = cli->getUid();
- netId = mDnsProxyListener->mNetCtrl->getNetwork(uid, netId, true);
- uint32_t mark = mDnsProxyListener->calcMark(cli, netId);
+ struct android_net_context netcontext;
+ mDnsProxyListener->mNetCtrl->getNetworkContext(netId, uid, &netcontext);
if (ai_flags != -1 || ai_family != -1 ||
ai_socktype != -1 || ai_protocol != -1) {
hints->ai_family = ai_family;
hints->ai_socktype = ai_socktype;
hints->ai_protocol = ai_protocol;
-
- // Only implement AI_ADDRCONFIG if application is using default network since our
- // implementation only works on the default network.
- if ((hints->ai_flags & AI_ADDRCONFIG) &&
- netId != mDnsProxyListener->mNetCtrl->getDefaultNetwork()) {
- hints->ai_flags &= ~AI_ADDRCONFIG;
- }
}
if (DBG) {
- ALOGD("GetAddrInfoHandler for %s / %s / %u / %d / %u",
+ ALOGD("GetAddrInfoHandler for %s / %s / {%u,%u,%u,%u,%u}",
name ? name : "[nullhost]",
service ? service : "[nullservice]",
- netId, uid, mark);
+ netcontext.app_netid, netcontext.app_mark,
+ netcontext.dns_netid, netcontext.dns_mark,
+ netcontext.uid);
}
cli->incRef();
DnsProxyListener::GetAddrInfoHandler* handler =
- new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, netId, mark);
+ new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, netcontext);
handler->start();
return 0;
name = strdup(name);
}
- netId = mDnsProxyListener->mNetCtrl->getNetwork(uid, netId, true);
- uint32_t mark = mDnsProxyListener->calcMark(cli, netId);
+ uint32_t mark = mDnsProxyListener->mNetCtrl->getNetworkForDns(&netId, uid);
cli->incRef();
DnsProxyListener::GetHostByNameHandler* handler =
return -1;
}
- netId = mDnsProxyListener->mNetCtrl->getNetwork(uid, netId, true);
- uint32_t mark = mDnsProxyListener->calcMark(cli, netId);
+ uint32_t mark = mDnsProxyListener->mNetCtrl->getNetworkForDns(&netId, uid);
cli->incRef();
DnsProxyListener::GetHostByAddrHandler* handler =