Browse Source

net: dns: Properly cleanup DNS servers per network interface

Make sure we cleanup only those DNS servers that belong to
certain network interface when the interface goes down.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
pull/91566/head
Jukka Rissanen 4 weeks ago committed by Henrik Brix Andersen
parent
commit
cb9052459a
  1. 10
      include/zephyr/net/dns_resolve.h
  2. 1
      subsys/net/ip/Kconfig.stack
  3. 6
      subsys/net/ip/ipv6_nbr.c
  4. 10
      subsys/net/lib/dhcpv4/dhcpv4.c
  5. 10
      subsys/net/lib/dhcpv6/dhcpv6.c
  6. 13
      subsys/net/lib/dns/Kconfig
  7. 479
      subsys/net/lib/dns/resolve.c
  8. 20
      tests/net/lib/dns_addremove/src/main.c
  9. 3
      tests/net/lib/dns_addremove/testcase.yaml
  10. 7
      tests/net/lib/dns_dispatcher/src/main.c
  11. 6
      tests/net/lib/dns_dispatcher/testcase.yaml

10
include/zephyr/net/dns_resolve.h

@ -550,6 +550,16 @@ int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx, @@ -550,6 +550,16 @@ int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx,
const struct sockaddr *servers_sa[],
int interfaces[]);
/**
* @brief Remove servers from the DNS resolving context.
*
* @param ctx DNS context
* @param if_index Network interface from which the DNS servers are removed.
*
* @return 0 if ok, <0 if error.
*/
int dns_resolve_remove(struct dns_resolve_context *ctx, int if_index);
/**
* @brief Cancel a pending DNS query.
*

1
subsys/net/ip/Kconfig.stack

@ -17,6 +17,7 @@ config NET_TX_STACK_SIZE @@ -17,6 +17,7 @@ config NET_TX_STACK_SIZE
config NET_RX_STACK_SIZE
int "RX thread stack size"
default 1792 if DNS_RESOLVER
default 1500
help
Set the RX thread stack size in bytes. The RX thread is waiting

6
subsys/net/ip/ipv6_nbr.c

@ -2469,6 +2469,9 @@ static inline bool handle_ra_rdnss(struct net_pkt *pkt, uint8_t len) @@ -2469,6 +2469,9 @@ static inline bool handle_ra_rdnss(struct net_pkt *pkt, uint8_t len)
const struct sockaddr *dns_servers[] = {
(struct sockaddr *)&dns, NULL
};
int interfaces[] = {
net_if_get_by_iface(net_pkt_iface(pkt))
};
size_t rdnss_size;
int ret;
@ -2505,7 +2508,8 @@ static inline bool handle_ra_rdnss(struct net_pkt *pkt, uint8_t len) @@ -2505,7 +2508,8 @@ static inline bool handle_ra_rdnss(struct net_pkt *pkt, uint8_t len)
/* TODO: Handle lifetime. */
ctx = dns_resolve_get_default();
ret = dns_resolve_reconfigure(ctx, NULL, dns_servers);
ret = dns_resolve_reconfigure_with_interfaces(ctx, NULL, dns_servers,
interfaces);
if (ret < 0) {
NET_DBG("Failed to set RDNSS resolve address: %d", ret);
}

10
subsys/net/lib/dhcpv4/dhcpv4.c

@ -1668,6 +1668,16 @@ static void dhcpv4_iface_event_handler(struct net_mgmt_event_callback *cb, @@ -1668,6 +1668,16 @@ static void dhcpv4_iface_event_handler(struct net_mgmt_event_callback *cb,
if (!net_if_ipv4_addr_rm(iface, &iface->config.dhcpv4.requested_ip)) {
NET_DBG("Failed to remove addr from iface");
}
/* Remove DNS servers as interface is gone. We only need to
* do this for this interface. If using global setting, the
* DNS servers are removed automatically when the interface
* comes back up.
*/
if (IS_ENABLED(CONFIG_NET_DHCPV4_DNS_SERVER_VIA_INTERFACE)) {
dns_resolve_remove(dns_resolve_get_default(),
net_if_get_by_iface(iface));
}
}
} else if (mgmt_event == NET_EVENT_IF_UP) {
NET_DBG("Interface %p coming up", iface);

10
subsys/net/lib/dhcpv6/dhcpv6.c

@ -2217,6 +2217,16 @@ static void dhcpv6_iface_event_handler(struct net_mgmt_event_callback *cb, @@ -2217,6 +2217,16 @@ static void dhcpv6_iface_event_handler(struct net_mgmt_event_callback *cb,
if (mgmt_event == NET_EVENT_IF_DOWN) {
NET_DBG("Interface %p going down", iface);
dhcpv6_set_timeout(iface, UINT64_MAX);
/* Remove DNS servers as interface is gone. We only need to
* do this for this interface. If using global setting, the
* DNS servers are removed automatically when the interface
* comes back up.
*/
if (IS_ENABLED(CONFIG_NET_DHCPV6_DNS_SERVER_VIA_INTERFACE)) {
dns_resolve_remove(dns_resolve_get_default(),
net_if_get_by_iface(iface));
}
} else if (mgmt_event == NET_EVENT_IF_UP) {
NET_DBG("Interface %p coming up", iface);
dhcpv6_enter_state(iface, NET_DHCPV6_INIT);

13
subsys/net/lib/dns/Kconfig

@ -121,6 +121,19 @@ config DNS_SERVER5 @@ -121,6 +121,19 @@ config DNS_SERVER5
endif # DNS_SERVER_IP_ADDRESSES
config DNS_RECONFIGURE_CLEANUP
bool "Cleanup old DNS server entries when reconfiguring"
help
If calling dns_resolve_reconfigure() when new DNS servers
are being set, for example if receiving new ones from DHCP server,
remove the old entries before setting up the new ones.
If you have only one network interface, then this can be enabled.
If you have multiple network interfaces, then this should be disabled
because the later configuration update would remove the entries
set by the other network interface configuration.
The previous default in Zephyr 4.1 or earlier was to have this enabled.
The current default in Zephyr 4.2 is to disable this option.
config DNS_NUM_CONCUR_QUERIES
int "Number of simultaneous DNS queries per one DNS context"
default 1

479
subsys/net/lib/dns/resolve.c

@ -81,6 +81,7 @@ NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR, @@ -81,6 +81,7 @@ NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR,
DNS_CACHE_DEFINE(dns_cache, CONFIG_DNS_RESOLVER_CACHE_MAX_ENTRIES);
#endif /* CONFIG_DNS_RESOLVER_CACHE */
static K_MUTEX_DEFINE(lock);
static int init_called;
static struct dns_resolve_context dns_default_ctx;
@ -414,12 +415,86 @@ static int bind_to_iface(int sock, const struct sockaddr *addr, int if_index) @@ -414,12 +415,86 @@ static int bind_to_iface(int sock, const struct sockaddr *addr, int if_index)
return ret;
}
static bool is_server_name_found(struct dns_resolve_context *ctx,
const char *server, size_t server_len,
const char *iface_str)
{
ARRAY_FOR_EACH(ctx->servers, i) {
if (ctx->servers[i].dns_server.sa_family == AF_INET ||
ctx->servers[i].dns_server.sa_family == AF_INET6) {
char addr_str[INET6_ADDRSTRLEN];
size_t addr_len;
if (net_addr_ntop(ctx->servers[i].dns_server.sa_family,
&net_sin(&ctx->servers[i].dns_server)->sin_addr,
addr_str, sizeof(addr_str)) < 0) {
continue;
}
addr_len = strlen(addr_str);
if (addr_len != server_len ||
strncmp(addr_str, server, server_len) != 0) {
continue;
}
if (iface_str != NULL && ctx->servers[i].if_index > 0) {
char iface_name[IFNAMSIZ];
net_if_get_name(net_if_get_by_index(
ctx->servers[i].if_index),
iface_name, sizeof(iface_name));
if (strcmp(iface_name, iface_str) != 0) {
continue;
}
}
return true;
}
}
return false;
}
static bool is_server_addr_found(struct dns_resolve_context *ctx,
const struct sockaddr *addr,
int if_index)
{
ARRAY_FOR_EACH(ctx->servers, i) {
if (ctx->servers[i].dns_server.sa_family == addr->sa_family &&
memcmp(&ctx->servers[i].dns_server, addr,
sizeof(ctx->servers[i].dns_server)) == 0) {
if (if_index == 0 ||
(if_index > 0 &&
ctx->servers[i].if_index != if_index)) {
continue;
}
return true;
}
}
return false;
}
static int get_free_slot(struct dns_resolve_context *ctx)
{
ARRAY_FOR_EACH(ctx->servers, i) {
if (ctx->servers[i].dns_server.sa_family == 0) {
return i;
}
}
return -ENOENT;
}
/* Must be invoked with context lock held */
static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
const char *servers[],
const struct sockaddr *servers_sa[],
const struct net_socket_service_desc *svc,
uint16_t port, int interfaces[])
uint16_t port, int interfaces[],
bool do_cleanup)
{
#if defined(CONFIG_NET_IPV6)
struct sockaddr_in6 local_addr6 = {
@ -445,17 +520,20 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, @@ -445,17 +520,20 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
return -ENOENT;
}
if (ctx->state != DNS_RESOLVE_CONTEXT_INACTIVE) {
ret = -ENOTEMPTY;
goto fail;
}
if (do_cleanup) {
if (ctx->state != DNS_RESOLVE_CONTEXT_INACTIVE) {
ret = -ENOTEMPTY;
NET_DBG("DNS resolver context is not inactive (%d)", ctx->state);
goto fail;
}
ARRAY_FOR_EACH(ctx->servers, j) {
ctx->servers[j].sock = -1;
}
ARRAY_FOR_EACH(ctx->servers, j) {
ctx->servers[j].sock = -1;
}
ARRAY_FOR_EACH(ctx->fds, j) {
ctx->fds[j].fd = -1;
ARRAY_FOR_EACH(ctx->fds, j) {
ctx->fds[j].fd = -1;
}
}
/* If user has provided a list of servers in string format, then
@ -464,78 +542,146 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, @@ -464,78 +542,146 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
* The interfaces parameter should point to an array that is the
* the same length as the servers_sa parameter array.
*/
if (servers) {
for (i = 0; idx < SERVER_COUNT && servers[i]; i++) {
const char *iface_str;
size_t server_len;
struct sockaddr *addr = &ctx->servers[idx].dns_server;
iface_str = strstr(servers[i], "%");
if (iface_str) {
server_len = iface_str - servers[i];
iface_str++;
for (i = 0; servers != NULL && idx < SERVER_COUNT && servers[i] != NULL; i++) {
const char *iface_str;
size_t server_len;
struct sockaddr *addr;
bool found;
iface_str = strstr(servers[i], "%");
if (iface_str != NULL) {
server_len = iface_str - servers[i];
iface_str++;
if (server_len == 0) {
NET_DBG("Empty server name");
continue;
}
if (server_len == 0) {
NET_DBG("Empty server name");
continue;
}
found = is_server_name_found(ctx, servers[i],
server_len, iface_str);
if (found) {
NET_DBG("Server %.*s already exists",
(int)server_len, servers[i]);
continue;
}
/* Skip empty interface name */
if (iface_str[0] == '\0') {
ctx->servers[idx].if_index = 0;
iface_str = NULL;
} else {
ctx->servers[idx].if_index =
net_if_get_by_name(iface_str);
}
/* Figure out if there are free slots where to add
* the server.
*/
idx = get_free_slot(ctx);
if (idx < 0) {
NET_DBG("No free slots for server %.*s",
(int)server_len, servers[i]);
break;
}
} else {
server_len = strlen(servers[i]);
/* Skip empty interface name */
if (iface_str[0] == '\0') {
ctx->servers[idx].if_index = 0;
iface_str = NULL;
} else {
ctx->servers[idx].if_index =
net_if_get_by_name(iface_str);
}
(void)memset(addr, 0, sizeof(*addr));
ret = net_ipaddr_parse(servers[i], server_len, addr);
if (!ret) {
if (servers[i] != NULL && servers[i][0] != '\0') {
NET_DBG("Invalid server address %.*s",
(int)server_len, servers[i]);
}
} else {
server_len = strlen(servers[i]);
if (server_len == 0) {
NET_DBG("Empty server name");
continue;
}
found = is_server_name_found(ctx, servers[i],
server_len, NULL);
if (found) {
NET_DBG("Server %.*s already exists",
(int)server_len, servers[i]);
continue;
}
dns_postprocess_server(ctx, idx);
idx = get_free_slot(ctx);
if (idx < 0) {
NET_DBG("No free slots for server %.*s",
(int)server_len, servers[i]);
break;
}
}
addr = &ctx->servers[idx].dns_server;
(void)memset(addr, 0, sizeof(*addr));
ret = net_ipaddr_parse(servers[i], server_len, addr);
if (!ret) {
if (servers[i][0] != '\0') {
NET_DBG("Invalid server address %.*s",
(int)server_len, servers[i]);
}
NET_DBG("[%d] %.*s%s%s%s%s", i, (int)server_len, servers[i],
IS_ENABLED(CONFIG_MDNS_RESOLVER) ?
(ctx->servers[i].is_mdns ? " mDNS" : "") : "",
IS_ENABLED(CONFIG_LLMNR_RESOLVER) ?
(ctx->servers[i].is_llmnr ? " LLMNR" : "") : "",
iface_str != NULL ? " via " : "",
iface_str != NULL ? iface_str : "");
idx++;
continue;
}
dns_postprocess_server(ctx, idx);
NET_DBG("[%d] %.*s%s%s%s%s", i, (int)server_len, servers[i],
IS_ENABLED(CONFIG_MDNS_RESOLVER) ?
(ctx->servers[i].is_mdns ? " mDNS" : "") : "",
IS_ENABLED(CONFIG_LLMNR_RESOLVER) ?
(ctx->servers[i].is_llmnr ? " LLMNR" : "") : "",
iface_str != NULL ? " via " : "",
iface_str != NULL ? iface_str : "");
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));
for (i = 0; servers_sa != NULL && idx < SERVER_COUNT && servers_sa[i] != NULL; i++) {
char iface_str[IFNAMSIZ] = { 0 };
bool found;
if (interfaces != NULL) {
ctx->servers[idx].if_index = interfaces[idx];
}
found = is_server_addr_found(ctx, servers_sa[i], interfaces[i]);
if (found) {
NET_DBG("Server %s already exists",
net_sprint_addr(ctx->servers[i].dns_server.sa_family,
&net_sin(&ctx->servers[i].dns_server)->sin_addr));
continue;
}
dns_postprocess_server(ctx, idx);
idx++;
/* Figure out if there are free slots where to add the server.
*/
idx = get_free_slot(ctx);
if (idx < 0) {
NET_DBG("No free slots for server %s",
net_sprint_addr(ctx->servers[i].dns_server.sa_family,
&net_sin(&ctx->servers[i].dns_server)->sin_addr));
break;
}
memcpy(&ctx->servers[idx].dns_server, servers_sa[i],
sizeof(ctx->servers[idx].dns_server));
if (interfaces != NULL) {
ctx->servers[idx].if_index = interfaces[i];
net_if_get_name(net_if_get_by_index(ctx->servers[idx].if_index),
iface_str, sizeof(iface_str));
}
dns_postprocess_server(ctx, idx);
NET_DBG("[%d] %s%s%s%s%s", i,
net_sprint_addr(servers_sa[i]->sa_family,
&net_sin(servers_sa[i])->sin_addr),
IS_ENABLED(CONFIG_MDNS_RESOLVER) ?
(ctx->servers[i].is_mdns ? " mDNS" : "") : "",
IS_ENABLED(CONFIG_LLMNR_RESOLVER) ?
(ctx->servers[i].is_llmnr ? " LLMNR" : "") : "",
interfaces != NULL ? " via " : "",
interfaces != NULL ? iface_str : "");
idx++;
}
for (i = 0, count = 0;
i < SERVER_COUNT && ctx->servers[i].dns_server.sa_family; i++) {
i < SERVER_COUNT && ctx->servers[i].dns_server.sa_family != 0; i++) {
if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
#if defined(CONFIG_NET_IPV6)
@ -571,6 +717,16 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, @@ -571,6 +717,16 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
goto fail;
}
if (ctx->servers[i].sock >= 0) {
/* Socket already exists, so skip it */
NET_DBG("Socket %d already exists for %s",
ctx->servers[i].sock,
net_sprint_addr(ctx->servers[i].dns_server.sa_family,
&net_sin(&ctx->servers[i].dns_server)->sin_addr));
count++;
continue;
}
ret = zsock_socket(ctx->servers[i].dns_server.sa_family,
SOCK_DGRAM, IPPROTO_UDP);
if (ret < 0) {
@ -589,6 +745,7 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, @@ -589,6 +745,7 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
if (ret < 0) {
zsock_close(ctx->servers[i].sock);
ctx->servers[i].sock = -1;
ctx->servers[i].dns_server.sa_family = 0;
continue;
}
@ -637,6 +794,8 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, @@ -637,6 +794,8 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
if (ret < 0) {
NET_DBG("Cannot set %s to socket (%d)", "polling", ret);
zsock_close(ctx->servers[i].sock);
ctx->servers[i].sock = -1;
ctx->servers[i].dns_server.sa_family = 0;
continue;
}
@ -695,20 +854,28 @@ int dns_resolve_init_with_svc(struct dns_resolve_context *ctx, const char *serve @@ -695,20 +854,28 @@ int dns_resolve_init_with_svc(struct dns_resolve_context *ctx, const char *serve
const struct net_socket_service_desc *svc,
uint16_t port, int interfaces[])
{
int ret;
if (!ctx) {
return -ENOENT;
}
(void)memset(ctx, 0, sizeof(*ctx));
k_mutex_lock(&lock, K_FOREVER);
(void)k_mutex_init(&ctx->lock);
ctx->state = DNS_RESOLVE_CONTEXT_INACTIVE;
/* Do cleanup only if we are starting the context for the first time */
if (init_called == 0) {
(void)memset(ctx, 0, sizeof(*ctx));
/* As this function is called only once during system init, there is no
* reason to acquire lock.
*/
return dns_resolve_init_locked(ctx, servers, servers_sa, svc, port,
interfaces);
(void)k_mutex_init(&ctx->lock);
ctx->state = DNS_RESOLVE_CONTEXT_INACTIVE;
}
ret = dns_resolve_init_locked(ctx, servers, servers_sa, svc, port,
interfaces, true);
k_mutex_unlock(&lock);
return ret;
}
int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[],
@ -1739,10 +1906,51 @@ int dns_resolve_name(struct dns_resolve_context *ctx, @@ -1739,10 +1906,51 @@ int dns_resolve_name(struct dns_resolve_context *ctx,
user_data, timeout, true);
}
static int dns_server_close(struct dns_resolve_context *ctx,
int server_idx)
{
struct net_if *iface;
if (ctx->servers[server_idx].sock < 0) {
return -ENOENT;
}
(void)dns_dispatcher_unregister(&ctx->servers[server_idx].dispatcher);
if (ctx->servers[server_idx].dns_server.sa_family == AF_INET6) {
iface = net_if_ipv6_select_src_iface(
&net_sin6(&ctx->servers[server_idx].dns_server)->sin6_addr);
} else {
iface = net_if_ipv4_select_src_iface(
&net_sin(&ctx->servers[server_idx].dns_server)->sin_addr);
}
if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) {
net_mgmt_event_notify_with_info(
NET_EVENT_DNS_SERVER_DEL,
iface,
(void *)&ctx->servers[server_idx].dns_server,
sizeof(struct sockaddr));
} else {
net_mgmt_event_notify(NET_EVENT_DNS_SERVER_DEL, iface);
}
zsock_close(ctx->servers[server_idx].sock);
ctx->servers[server_idx].sock = -1;
ctx->servers[server_idx].dns_server.sa_family = 0;
ARRAY_FOR_EACH(ctx->fds, j) {
ctx->fds[j].fd = -1;
}
return 0;
}
/* Must be invoked with context lock held */
static int dns_resolve_close_locked(struct dns_resolve_context *ctx)
{
int i;
int i, ret;
if (ctx->state != DNS_RESOLVE_CONTEXT_ACTIVE) {
return -ENOENT;
@ -1762,44 +1970,10 @@ static int dns_resolve_close_locked(struct dns_resolve_context *ctx) @@ -1762,44 +1970,10 @@ static int dns_resolve_close_locked(struct dns_resolve_context *ctx)
k_mutex_unlock(&ctx->lock);
for (i = 0; i < SERVER_COUNT; i++) {
struct net_if *iface;
if (ctx->servers[i].sock < 0) {
continue;
}
(void)dns_dispatcher_unregister(&ctx->servers[i].dispatcher);
if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
iface = net_if_ipv6_select_src_iface(
&net_sin6(&ctx->servers[i].dns_server)->sin6_addr);
} else {
iface = net_if_ipv4_select_src_iface(
&net_sin(&ctx->servers[i].dns_server)->sin_addr);
}
if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) {
net_mgmt_event_notify_with_info(
NET_EVENT_DNS_SERVER_DEL,
iface,
(void *)&ctx->servers[i].dns_server,
sizeof(struct sockaddr));
} else {
net_mgmt_event_notify(NET_EVENT_DNS_SERVER_DEL,
iface);
}
zsock_close(ctx->servers[i].sock);
ARRAY_FOR_EACH(ctx->fds, j) {
if (ctx->fds[j].fd == ctx->servers[i].sock) {
ctx->fds[j].fd = -1;
}
ret = dns_server_close(ctx, i);
if (ret < 0) {
NET_DBG("Cannot close DNS server %d (%d)", i, ret);
}
(void)dns_dispatcher_unregister(&ctx->servers[i].dispatcher);
ctx->servers[i].sock = -1;
}
if (--init_called <= 0) {
@ -1877,10 +2051,11 @@ static bool dns_servers_exists(struct dns_resolve_context *ctx, @@ -1877,10 +2051,11 @@ static bool dns_servers_exists(struct dns_resolve_context *ctx,
return true;
}
int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx,
const char *servers[],
const struct sockaddr *servers_sa[],
int interfaces[])
static int do_dns_resolve_reconfigure(struct dns_resolve_context *ctx,
const char *servers[],
const struct sockaddr *servers_sa[],
int interfaces[],
bool do_close)
{
int err;
@ -1888,6 +2063,7 @@ int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx, @@ -1888,6 +2063,7 @@ int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx,
return -ENOENT;
}
k_mutex_lock(&lock, K_FOREVER);
k_mutex_lock(&ctx->lock, K_FOREVER);
if (dns_servers_exists(ctx, servers, servers_sa)) {
@ -1901,32 +2077,99 @@ int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx, @@ -1901,32 +2077,99 @@ int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx,
goto unlock;
}
if (ctx->state == DNS_RESOLVE_CONTEXT_ACTIVE) {
if (ctx->state == DNS_RESOLVE_CONTEXT_ACTIVE &&
(do_close || init_called == 0)) {
dns_resolve_cancel_all(ctx);
err = dns_resolve_close_locked(ctx);
if (err) {
goto unlock;
}
/* Make sure we do fresh start once */
do_close = true;
}
err = dns_resolve_init_locked(ctx, servers, servers_sa,
&resolve_svc, 0, interfaces);
&resolve_svc, 0, interfaces,
do_close);
unlock:
k_mutex_unlock(&ctx->lock);
k_mutex_unlock(&lock);
return err;
}
int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx,
const char *servers[],
const struct sockaddr *servers_sa[],
int interfaces[])
{
return do_dns_resolve_reconfigure(ctx,
servers,
servers_sa,
interfaces,
IS_ENABLED(CONFIG_DNS_RECONFIGURE_CLEANUP) ?
true : false);
}
int dns_resolve_reconfigure(struct dns_resolve_context *ctx,
const char *servers[],
const struct sockaddr *servers_sa[])
{
return dns_resolve_reconfigure_with_interfaces(ctx,
servers,
servers_sa,
NULL);
return do_dns_resolve_reconfigure(ctx,
servers,
servers_sa,
NULL,
IS_ENABLED(CONFIG_DNS_RECONFIGURE_CLEANUP) ?
true : false);
}
int dns_resolve_remove(struct dns_resolve_context *ctx, int if_index)
{
int i;
int ret = -ENOENT;
int st = 0;
if (!ctx) {
return -ENOENT;
}
if (if_index <= 0) {
/* If network interface index is 0, then do nothing.
* If your want to remove all the servers, then just call
* dns_resolve_close() directly.
*/
return -EINVAL;
}
k_mutex_lock(&ctx->lock, K_FOREVER);
for (i = 0; i < SERVER_COUNT; i++) {
if (ctx->servers[i].if_index != if_index) {
continue;
}
ctx->servers[i].if_index = 0;
/* See comment in dns_resolve_close_locked() about
* releasing the lock before closing the server socket.
*/
k_mutex_unlock(&ctx->lock);
ret = dns_server_close(ctx, i);
k_mutex_lock(&ctx->lock, K_FOREVER);
if (ret < 0) {
st = ret;
}
}
k_mutex_unlock(&ctx->lock);
return st;
}
struct dns_resolve_context *dns_resolve_get_default(void)

20
tests/net/lib/dns_addremove/src/main.c

@ -470,15 +470,17 @@ ZTEST(dns_addremove, test_dns_reconfigure_callback) @@ -470,15 +470,17 @@ ZTEST(dns_addremove, test_dns_reconfigure_callback)
zassert_equal(ret, 0, "Cannot reconfigure DNS server");
/* Wait for DNS removed callback after reconfiguring DNS */
if (k_sem_take(&dns_removed, WAIT_TIME)) {
zassert_true(false,
"Timeout while waiting for DNS removed callback");
}
/* Wait for DNS added callback after reconfiguring DNS */
if (k_sem_take(&dns_added, WAIT_TIME)) {
zassert_true(false,
"Timeout while waiting for DNS added callback");
if (IS_ENABLED(CONFIG_DNS_RECONFIGURE_CLEANUP)) {
if (k_sem_take(&dns_removed, WAIT_TIME)) {
zassert_true(false,
"Timeout while waiting for DNS removed callback");
}
/* Wait for DNS added callback after reconfiguring DNS */
if (k_sem_take(&dns_added, WAIT_TIME)) {
zassert_true(false,
"Timeout while waiting for DNS added callback");
}
}
ret = dns_resolve_close(&resv_ipv4);

3
tests/net/lib/dns_addremove/testcase.yaml

@ -14,3 +14,6 @@ tests: @@ -14,3 +14,6 @@ tests:
net.dns.no_ipv4:
extra_configs:
- CONFIG_NET_IPV4=n
net.dns.addremove.reconfigure_cleanup:
extra_configs:
- CONFIG_DNS_RECONFIGURE_CLEANUP=y

7
tests/net/lib/dns_dispatcher/src/main.c

@ -175,11 +175,14 @@ static void *test_init(void) @@ -175,11 +175,14 @@ static void *test_init(void)
ZTEST(dns_dispatcher, test_dns_dispatcher)
{
struct dns_resolve_context *ctx;
int sock1, sock2 = -1;
int ret, sock1, sock2 = -1;
ctx = dns_resolve_get_default();
dns_resolve_init_default(ctx);
dns_resolve_close(ctx);
ret = dns_resolve_init_default(ctx);
zassert_equal(ret, 0, "Cannot initialize DNS resolver (%d)", ret);
sock1 = ctx->servers[0].sock;

6
tests/net/lib/dns_dispatcher/testcase.yaml

@ -8,3 +8,9 @@ common: @@ -8,3 +8,9 @@ common:
tests:
net.dns.dispatch:
min_ram: 21
net.dns.dispatch.ctx_cleanup:
extra_configs:
- CONFIG_DNS_RECONFIGURE_CLEANUP=y
net.dns.dispatch.ctx_no_cleanup:
extra_configs:
- CONFIG_DNS_RECONFIGURE_CLEANUP=n

Loading…
Cancel
Save