Commit d965598e authored by Paul Sokolovsky's avatar Paul Sokolovsky Committed by Jukka Rissanen
Browse files

net: dns: Allow to initialize DNS servers from struct sockaddr[]



In some cases, we need to initialize DNS servers from a binary
addresses, e.g. in case of DHCP processing. With existing API,
such addresses would need to be converted to strings, just to
be converted back to struct sockaddr in dns_resolve_init().
This is not efficient, and with a number of addresses quite
cumbersome. So instead, allow to pass DNS server either as
strings, or as struct sockaddr's (or both).

Signed-off-by: default avatarPaul Sokolovsky <paul.sokolovsky@linaro.org>
parent a3231798
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -176,7 +176,8 @@ struct dns_resolve_context {
 * @brief Init DNS resolving context.
 *
 * @details This function sets the DNS server address and initializes the
 * DNS context that is used by the actual resolver.
 * DNS context that is used by the actual resolver. DNS server addresses
 * can be specified either in textual form, or as struct sockaddr (or both).
 * Note that the recommended way to resolve DNS names is to use
 * the dns_get_addr_info() API. In that case user does not need to
 * call dns_resolve_init() as the DNS servers are already setup by the system.
@@ -185,18 +186,22 @@ struct dns_resolve_context {
 * the stack, then the variable needs to be valid for the whole duration of
 * the resolving. Caller does not need to fill the variable beforehand or
 * edit the context afterwards.
 * @param dns_servers DNS server addresses. The array is null terminated.
 * The port number can be given in the string.
 * @param dns_servers_str DNS server addresses using textual strings. The
 * array is NULL terminated. The port number can be given in the string.
 * Syntax for the server addresses with or without port numbers:
 *    IPv4        : 10.0.9.1
 *    IPv4 + port : 10.0.9.1:5353
 *    IPv6        : 2001:db8::22:42
 *    IPv6 + port : [2001:db8::22:42]:5353
 * @param dns_servers_sa DNS server addresses as struct sockaddr. The array
 * is NULL terminated. Port numbers are optional in struct sockaddr, the
 * default will be used if set to 0.
 *
 * @return 0 if ok, <0 if error.
 */
int dns_resolve_init(struct dns_resolve_context *ctx,
		     const char *dns_servers[]);
		     const char *dns_servers_str[],
		     const struct sockaddr *dns_servers_sa[]);

/**
 * @brief Close DNS resolving context.
+65 −49
Original line number Diff line number Diff line
@@ -77,49 +77,10 @@ NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR, DNS_MAX_NAME_LEN,

static struct dns_resolve_context dns_default_ctx;

int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
static void dns_postprocess_server(struct dns_resolve_context *ctx, int idx)
{
#if defined(CONFIG_NET_IPV6)
	struct sockaddr_in6 local_addr6 = {
		.sin6_family = AF_INET6,
		.sin6_port = 0,
	};
#endif
#if defined(CONFIG_NET_IPV4)
	struct sockaddr_in local_addr4 = {
		.sin_family = AF_INET,
		.sin_port = 0,
	};
#endif
	struct sockaddr *local_addr = NULL;
	socklen_t addr_len = 0;
	int i = 0, idx = 0;
	int ret, count;

	if (!ctx) {
		return -ENOENT;
	}

	if (!servers || !*servers) {
		return -ENOENT;
	}

	if (ctx->is_used) {
		return -ENOTEMPTY;
	}

	memset(ctx, 0, sizeof(*ctx));

	for (i = 0; i < SERVER_COUNT && servers[i]; i++) {
	struct sockaddr *addr = &ctx->servers[idx].dns_server;

		memset(addr, 0, sizeof(*addr));

		ret = net_ipaddr_parse(servers[i], strlen(servers[i]), addr);
		if (!ret) {
			continue;
		}

	if (addr->sa_family == AF_INET) {
		if (net_is_ipv4_addr_mcast(&net_sin(addr)->sin_addr)) {
			ctx->servers[idx].is_mdns = true;
@@ -156,11 +117,66 @@ int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
			}
		}
	}
}

int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[],
		     const struct sockaddr *servers_sa[])
{
#if defined(CONFIG_NET_IPV6)
	struct sockaddr_in6 local_addr6 = {
		.sin6_family = AF_INET6,
		.sin6_port = 0,
	};
#endif
#if defined(CONFIG_NET_IPV4)
	struct sockaddr_in local_addr4 = {
		.sin_family = AF_INET,
		.sin_port = 0,
	};
#endif
	struct sockaddr *local_addr = NULL;
	socklen_t addr_len = 0;
	int i = 0, idx = 0;
	int ret, count;

	if (!ctx) {
		return -ENOENT;
	}

	if (ctx->is_used) {
		return -ENOTEMPTY;
	}

	memset(ctx, 0, sizeof(*ctx));

	if (servers) {
		for (i = 0; idx < SERVER_COUNT && servers[i]; i++) {
			struct sockaddr *addr = &ctx->servers[idx].dns_server;

			memset(addr, 0, sizeof(*addr));

			ret = net_ipaddr_parse(servers[i], strlen(servers[i]),
					       addr);
			if (!ret) {
				continue;
			}

			dns_postprocess_server(ctx, idx);

			NET_DBG("[%d] %s", i, servers[i]);

			idx++;
		}
	}

	if (servers_sa) {
		for (i = 0; idx < SERVER_COUNT && servers_sa[i]; i++) {
			memcpy(&ctx->servers[idx].dns_server, servers_sa[i],
			       sizeof(ctx->servers[idx].dns_server));
			dns_postprocess_server(ctx, idx);
			idx++;
		}
	}

	for (i = 0, count = 0;
	     i < SERVER_COUNT && ctx->servers[i].dns_server.sa_family; i++) {
@@ -904,7 +920,7 @@ void dns_init_resolver(void)

	dns_servers[SERVER_COUNT] = NULL;

	ret = dns_resolve_init(dns_resolve_get_default(), dns_servers);
	ret = dns_resolve_init(dns_resolve_get_default(), dns_servers, NULL);
	if (ret < 0) {
		NET_WARN("Cannot initialize DNS resolver (%d)", ret);
	}