Skip to content

Commit

Permalink
net: dns: Check family before returning results
Browse files Browse the repository at this point in the history
If we are returned IPv4 address but the hints says IPv6, then
return error as currently we do not support AI_V4MAPPED addresses.
Same check for IPv6 if we want only IPv4 address.

Fixes #18870

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
  • Loading branch information
jukkar committed Sep 11, 2019
1 parent fb4e1da commit 06d101e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
26 changes: 26 additions & 0 deletions subsys/net/lib/dns/resolve.c
Expand Up @@ -435,12 +435,22 @@ static int dns_read(struct dns_resolve_context *ctx,
}

if (ctx->queries[query_idx].query_type == DNS_QUERY_TYPE_A) {
if (net_sin(&info.ai_addr)->sin_family == AF_INET6) {
ret = DNS_EAI_ADDRFAMILY;
goto quit;
}

address_size = DNS_IPV4_LEN;
addr = (u8_t *)&net_sin(&info.ai_addr)->sin_addr;
info.ai_family = AF_INET;
info.ai_addr.sa_family = AF_INET;
info.ai_addrlen = sizeof(struct sockaddr_in);
} else if (ctx->queries[query_idx].query_type == DNS_QUERY_TYPE_AAAA) {
if (net_sin6(&info.ai_addr)->sin6_family == AF_INET) {
ret = DNS_EAI_ADDRFAMILY;
goto quit;
}

/* We cannot resolve IPv6 address if IPv6 is disabled. The reason
* being that "struct sockaddr" does not have enough space for
* IPv6 address in that case.
Expand Down Expand Up @@ -789,12 +799,28 @@ int dns_resolve_name(struct dns_resolve_context *ctx,
struct dns_addrinfo info = { 0 };

if (type == DNS_QUERY_TYPE_A) {
if (net_sin(&addr)->sin_family == AF_INET6) {
ret = -EPFNOSUPPORT;
goto quit;
}

memcpy(net_sin(&info.ai_addr), net_sin(&addr),
sizeof(struct sockaddr_in));
info.ai_family = AF_INET;
info.ai_addr.sa_family = AF_INET;
info.ai_addrlen = sizeof(struct sockaddr_in);
} else if (type == DNS_QUERY_TYPE_AAAA) {
/* We do not support AI_V4MAPPED atm, so if the user
* asks an IPv6 address but it is an IPv4 one, then
* return an error. Note that getaddrinfo() will swap
* the error to EINVAL, the EPFNOSUPPORT is returned
* here so that we can find it easily.
*/
if (net_sin(&addr)->sin_family == AF_INET) {
ret = -EPFNOSUPPORT;
goto quit;
}

#if defined(CONFIG_NET_IPV6)
memcpy(net_sin6(&info.ai_addr), net_sin6(&addr),
sizeof(struct sockaddr_in6));
Expand Down
13 changes: 11 additions & 2 deletions subsys/net/lib/sockets/getaddrinfo.c
Expand Up @@ -223,8 +223,17 @@ int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,

st1 = ai_state.status;
} else {
errno = -ret;
st1 = DNS_EAI_SYSTEM;
/* If we are returned -EPFNOSUPPORT then that will indicate
* wrong address family type queried. Check that and return
* DNS_EAI_ADDRFAMILY and set errno to EINVAL.
*/
if (ret == -EPFNOSUPPORT) {
errno = EINVAL;
st1 = DNS_EAI_ADDRFAMILY;
} else {
errno = -ret;
st1 = DNS_EAI_SYSTEM;
}
}

/* If family is AF_UNSPEC, the IPv4 query has been already done
Expand Down

0 comments on commit 06d101e

Please sign in to comment.