Files
frameworks_base/native/android/net.c
Luke Huang c17821cc11 Add asynchronous DNS query API
Adds support for asynchronous "raw" DNS API for clients.
API allows apps to use multinetworking capability correctly
and also allows other query types than A/AAAA.

Test: built, flashed, booted
      cts test: NativeDnsAsyncTest

Change-Id: I4701b76bd8f0094ef1bdd7c5371b54387914a91b
2018-12-12 04:17:41 +08:00

114 lines
3.1 KiB
C

/*
* Copyright (C) 2015 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 <android/multinetwork.h>
#include <errno.h>
#include <NetdClient.h> // the functions that communicate with netd
#include <resolv_netid.h> // android_getaddrinfofornet()
#include <stdlib.h>
#include <sys/limits.h>
static int getnetidfromhandle(net_handle_t handle, unsigned *netid) {
static const uint32_t k32BitMask = 0xffffffff;
// This value MUST be kept in sync with the corresponding value in
// the android.net.Network#getNetworkHandle() implementation.
static const uint32_t kHandleMagic = 0xcafed00d;
// Check for minimum acceptable version of the API in the low bits.
if (handle != NETWORK_UNSPECIFIED &&
(handle & k32BitMask) != kHandleMagic) {
return 0;
}
if (netid != NULL) {
*netid = ((handle >> (CHAR_BIT * sizeof(k32BitMask))) & k32BitMask);
}
return 1;
}
int android_setsocknetwork(net_handle_t network, int fd) {
unsigned netid;
if (!getnetidfromhandle(network, &netid)) {
errno = EINVAL;
return -1;
}
int rval = setNetworkForSocket(netid, fd);
if (rval < 0) {
errno = -rval;
rval = -1;
}
return rval;
}
int android_setprocnetwork(net_handle_t network) {
unsigned netid;
if (!getnetidfromhandle(network, &netid)) {
errno = EINVAL;
return -1;
}
int rval = setNetworkForProcess(netid);
if (rval < 0) {
errno = -rval;
rval = -1;
}
return rval;
}
int android_getaddrinfofornetwork(net_handle_t network,
const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res) {
unsigned netid;
if (!getnetidfromhandle(network, &netid)) {
errno = EINVAL;
return EAI_SYSTEM;
}
return android_getaddrinfofornet(node, service, hints, netid, 0, res);
}
int android_res_nquery(net_handle_t network,
const char *dname, int ns_class, int ns_type) {
unsigned netid;
if (!getnetidfromhandle(network, &netid)) {
return -ENONET;
}
return resNetworkQuery(netid, dname, ns_class, ns_type);
}
int android_res_nresult(int fd, int *rcode, unsigned char *answer, int anslen) {
return resNetworkResult(fd, rcode, answer, anslen);
}
int android_res_nsend(net_handle_t network,
const unsigned char *msg, int msglen) {
unsigned netid;
if (!getnetidfromhandle(network, &netid)) {
return -ENONET;
}
return resNetworkSend(netid, msg, msglen);
}
void android_res_cancel(int nsend_fd) {
resNetworkCancel(nsend_fd);
}