Unify DNS error code for android_gethostbyaddrfornetcontext
Both gethostbyname and getaddrinfo return error code POSIX EAI_* now. Unify
the error codes of gethostbyaddr to be POSIX EAI_* as well.
Test: system/netd/tests/runtests.sh passed
Change-Id: Iee6963e2ebd21fd0c446b487784eb59af37a544e
diff --git a/resolv/gethnamaddr.cpp b/resolv/gethnamaddr.cpp
index 53abe12..0ccc3d7 100644
--- a/resolv/gethnamaddr.cpp
+++ b/resolv/gethnamaddr.cpp
@@ -135,8 +135,8 @@
static void pad_v4v6_hostent(struct hostent* hp, char** bpp, char* ep);
static void addrsort(char**, int, res_state);
-static bool _dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
- const android_net_context* netcontext, getnamaddr* info);
+static int _dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
+ const android_net_context* netcontext, getnamaddr* info);
static int _dns_gethtbyname(const char* name, int af, getnamaddr* info);
static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
@@ -144,11 +144,12 @@
const android_net_context* netcontext);
static int gethostbyname_internal_real(const char* name, int af, res_state res, hostent* hp,
char* buf, size_t buflen, int* he);
-static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(
- const void*, socklen_t, int, struct hostent*, char*, size_t, int*,
- const struct android_net_context*);
-static struct hostent* android_gethostbyaddrfornetcontext_proxy(
- const void* addr, socklen_t len, int af, const struct android_net_context* netcontext);
+static int android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t, int,
+ struct hostent*, char*, size_t, int*,
+ const struct android_net_context*);
+static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
+ const struct android_net_context* netcontext,
+ hostent** hp);
#ifdef DEBUG
static void debugprintf(const char* msg, res_state res, ...) {
@@ -573,9 +574,10 @@
return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
}
-static struct hostent* android_gethostbyaddrfornetcontext_real(
- const void* addr, socklen_t len, int af, struct hostent* hp, char* buf, size_t buflen,
- int* he, const struct android_net_context* netcontext) {
+static int android_gethostbyaddrfornetcontext_real(const void* addr, socklen_t len, int af,
+ struct hostent* hp, char* buf, size_t buflen,
+ int* he,
+ const struct android_net_context* netcontext) {
const u_char* uaddr = (const u_char*) addr;
socklen_t size;
struct getnamaddr info;
@@ -586,7 +588,7 @@
(IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) ||
IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) {
*he = HOST_NOT_FOUND;
- return NULL;
+ return EAI_NODATA;
}
if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
(IN6_IS_ADDR_V4MAPPED((const struct in6_addr*) addr) ||
@@ -607,12 +609,13 @@
default:
errno = EAFNOSUPPORT;
*he = NETDB_INTERNAL;
- return NULL;
+ return EAI_FAMILY;
}
if (size != len) {
errno = EINVAL;
*he = NETDB_INTERNAL;
- return NULL;
+ // TODO: Consider to remap error code without relying on errno.
+ return EAI_SYSTEM;
}
info.hp = hp;
info.buf = buf;
@@ -620,15 +623,16 @@
info.he = he;
*he = NETDB_INTERNAL;
if (!_hf_gethtbyaddr(uaddr, len, af, &info)) {
- if (!_dns_gethtbyaddr(uaddr, len, af, netcontext, &info)) {
- return NULL;
+ int error = _dns_gethtbyaddr(uaddr, len, af, netcontext, &info);
+ if (error != 0) {
+ return error;
}
}
*he = NETDB_SUCCESS;
- return hp;
+ return 0;
}
-static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(
+static int android_gethostbyaddrfornetcontext_proxy_internal(
const void* addr, socklen_t len, int af, struct hostent* hp, char* hbuf, size_t hbuflen,
int* he, const struct android_net_context* netcontext) {
return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, he,
@@ -895,8 +899,8 @@
return 0;
}
-static bool _dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
- const android_net_context* netcontext, getnamaddr* info) {
+static int _dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
+ const android_net_context* netcontext, getnamaddr* info) {
char qbuf[MAXDNAME + 1], *qp, *ep;
int n;
struct hostent* hp;
@@ -922,27 +926,29 @@
qp += advance;
else {
*info->he = NETDB_INTERNAL;
- return false;
+ // TODO: Consider to remap error code without relying on errno.
+ return EAI_SYSTEM;
}
}
if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
*info->he = NETDB_INTERNAL;
- return false;
+ // TODO: Consider to remap error code without relying on errno.
+ return EAI_SYSTEM;
}
break;
default:
- return false;
+ return EAI_FAMILY;
}
querybuf* buf = (querybuf*) malloc(sizeof(querybuf));
if (buf == NULL) {
*info->he = NETDB_INTERNAL;
- return false;
+ return EAI_MEMORY;
}
res = res_get_state();
if (res == NULL) {
free(buf);
- return false;
+ return EAI_MEMORY;
}
res_setnetcontext(res, netcontext);
int ai_error = 0;
@@ -950,12 +956,19 @@
if (n < 0) {
free(buf);
debugprintf("res_nquery failed (%d)\n", res, n);
- return false;
+
+ // TODO: Consider to return more meaningful error codes.
+ // Currently, doesn't consider ai_error as _dns_gethtbyname() does because current ai_error
+ // comes from rcode only and rcode NOERROR doesn't really mean no error for the whole DNS
+ // query progress. DNS server may respond a DNS packet without any answer for queried
+ // address. In this case, return error code from h_errno NO_DATA rather than rcode NOERROR
+ // (ai_error).
+ return herrnoToAiError(h_errno);
}
hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, info->he);
free(buf);
if (hp == NULL) {
- return false;
+ return herrnoToAiError(h_errno);
}
char* bf = (char*) (hp->h_addr_list + 2);
@@ -979,12 +992,12 @@
}
*info->he = NETDB_SUCCESS;
- return true;
+ return 0;
nospc:
errno = ENOSPC;
*info->he = NETDB_INTERNAL;
- return false;
+ return EAI_MEMORY;
}
/*
@@ -1005,16 +1018,19 @@
return error;
}
-struct hostent* android_gethostbyaddrfornetcontext(const void* addr, socklen_t len, int af,
- const struct android_net_context* netcontext) {
- return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
+int android_gethostbyaddrfornetcontext(const void* addr, socklen_t len, int af,
+ const struct android_net_context* netcontext, hostent** hp) {
+ return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext, hp);
}
-static struct hostent* android_gethostbyaddrfornetcontext_proxy(
- const void* addr, socklen_t len, int af, const struct android_net_context* netcontext) {
+static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
+ const struct android_net_context* netcontext,
+ hostent** hp) {
struct res_static* rs = res_get_static(); // For thread-safety.
- return android_gethostbyaddrfornetcontext_proxy_internal(
+ int error = android_gethostbyaddrfornetcontext_proxy_internal(
addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno, netcontext);
+ if (error == 0) *hp = &rs->host;
+ return error;
}
int herrnoToAiError(int herror) {
diff --git a/resolv/include/netd_resolv/resolv.h b/resolv/include/netd_resolv/resolv.h
index 9989766..e30f31a 100644
--- a/resolv/include/netd_resolv/resolv.h
+++ b/resolv/include/netd_resolv/resolv.h
@@ -102,8 +102,8 @@
typedef void (*private_dns_validated_callback)(unsigned netid, const char* server,
const char* hostname, bool success);
-LIBNETD_RESOLV_PUBLIC hostent* android_gethostbyaddrfornetcontext(const void*, socklen_t, int,
- const android_net_context*);
+LIBNETD_RESOLV_PUBLIC int android_gethostbyaddrfornetcontext(const void*, socklen_t, int,
+ const android_net_context*, hostent**);
LIBNETD_RESOLV_PUBLIC int android_gethostbynamefornetcontext(const char*, int,
const android_net_context*, hostent**);
LIBNETD_RESOLV_PUBLIC int android_getaddrinfofornetcontext(const char*, const char*,
diff --git a/resolv/include/netd_resolv/resolv_stub.h b/resolv/include/netd_resolv/resolv_stub.h
index a2462bd..fddabcf 100644
--- a/resolv/include/netd_resolv/resolv_stub.h
+++ b/resolv/include/netd_resolv/resolv_stub.h
@@ -37,8 +37,8 @@
int (*android_getaddrinfofornetcontext)(const char*, const char*, const addrinfo*,
const android_net_context*, addrinfo**);
- hostent* (*android_gethostbyaddrfornetcontext)(const void*, socklen_t, int,
- const android_net_context*);
+ int (*android_gethostbyaddrfornetcontext)(const void*, socklen_t, int,
+ const android_net_context*, hostent**);
int (*android_gethostbynamefornetcontext)(const char*, int, const android_net_context*,
hostent**);