Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/zephyr/net/dns_resolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ struct dns_resolve_context {
/** Connection to the DNS server */
int sock;

/** Network interface index if the DNS resolving should be done
* via this interface. Value 0 indicates any interface can be used.
*/
int if_index;

/** Is this server mDNS one */
uint8_t is_mdns : 1;

Expand Down
3 changes: 3 additions & 0 deletions samples/net/mdns_responder/overlay-vlan.conf
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ CONFIG_NET_SAMPLE_IFACE3_VLAN_TAG=200
# we do not run out of them.
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_MAX_CONN=10

CONFIG_NET_INTERFACE_NAME=y
CONFIG_NET_INTERFACE_NAME_LEN=15
4 changes: 2 additions & 2 deletions subsys/net/ip/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -864,8 +864,8 @@ static bool parse_ipv4(const char *str, size_t str_len,
return true;
}

memcpy(ipaddr, ptr + 1, str_len - end);
ipaddr[str_len - end] = '\0';
memcpy(ipaddr, ptr + 1, str_len - end - 1);
ipaddr[str_len - end - 1] = '\0';

ret = convert_port(ipaddr, &port);
if (!ret) {
Expand Down
6 changes: 6 additions & 0 deletions subsys/net/lib/dns/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ config DNS_SERVER1
192.0.2.1:5353
2001:db8::1
[2001:db8::1]:5353
It is possible to bind the DNS connection via a certain network
interface by appending "%" and network interface name to the server
address. For example: 192.0.2.1%eth1 would bind the connection socket
to the network interface eth1. This is optional and by default the
resolver connects to server by selecting the output network interface
using normal IP routing.
It is not mandatory to use this Kconfig option at all.
The one calling dns_resolve_init() can use this option or not
to populate the server list. If the DNS server addresses are
Expand Down
98 changes: 91 additions & 7 deletions subsys/net/lib/dns/resolve.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <zephyr/net/net_mgmt.h>
#include <zephyr/net/dns_resolve.h>
#include <zephyr/net/socket_service.h>
#include "../../ip/net_private.h"
#include "dns_pack.h"
#include "dns_internal.h"
#include "dns_cache.h"
Expand Down Expand Up @@ -319,6 +320,31 @@
return dns_dispatcher_register(&server->dispatcher);
}

static int bind_to_iface(int sock, const struct sockaddr *addr, int if_index)
{
struct ifreq ifreq = { 0 };
int ret;

Check notice on line 326 in subsys/net/lib/dns/resolve.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/dns/resolve.c:326 - struct ifreq ifreq = { 0 }; + struct ifreq ifreq = {0};

ret = net_if_get_name(net_if_get_by_index(if_index), ifreq.ifr_name,
sizeof(ifreq.ifr_name));
if (ret < 0) {
LOG_DBG("Cannot get interface name for %d (%d)", if_index, ret);
return ret;
}

ret = zsock_setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
&ifreq, sizeof(ifreq));
if (ret < 0) {
ret = -errno;

NET_DBG("Cannot bind %s to %d (%d)",
net_sprint_addr(addr->sa_family, &net_sin(addr)->sin_addr),
if_index, ret);
}

Check notice on line 343 in subsys/net/lib/dns/resolve.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/dns/resolve.c:343 - ret = zsock_setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, - &ifreq, sizeof(ifreq)); + ret = zsock_setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq)); if (ret < 0) { ret = -errno; NET_DBG("Cannot bind %s to %d (%d)", - net_sprint_addr(addr->sa_family, &net_sin(addr)->sin_addr), - if_index, ret); + net_sprint_addr(addr->sa_family, &net_sin(addr)->sin_addr), if_index, ret);

return ret;
}

/* Must be invoked with context lock held */
static int dns_resolve_init_locked(struct dns_resolve_context *ctx,
const char *servers[],
Expand Down Expand Up @@ -363,24 +389,56 @@

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++;

if (server_len == 0) {
NET_DBG("Empty server name");
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);
}

Check notice on line 414 in subsys/net/lib/dns/resolve.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/dns/resolve.c:414 - ctx->servers[idx].if_index = - net_if_get_by_name(iface_str); + ctx->servers[idx].if_index = net_if_get_by_name(iface_str);

} else {
server_len = strlen(servers[i]);
ctx->servers[idx].if_index = 0;
}

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

ret = net_ipaddr_parse(servers[i], strlen(servers[i]),
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",
server_len, servers[i]);
}

Check notice on line 428 in subsys/net/lib/dns/resolve.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/dns/resolve.c:428 - NET_DBG("Invalid server address %.*s", - server_len, servers[i]); + NET_DBG("Invalid server address %.*s", server_len, + servers[i]);

continue;
}

dns_postprocess_server(ctx, idx);

NET_DBG("[%d] %s%s%s", i, servers[i],
NET_DBG("[%d] %.*s%s%s%s%s", i, 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" : "") : "");
(ctx->servers[i].is_llmnr ? " LLMNR" : "") : "",
iface_str != NULL ? " via " : "",

Check notice on line 440 in subsys/net/lib/dns/resolve.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/dns/resolve.c:440 - IS_ENABLED(CONFIG_MDNS_RESOLVER) ? - (ctx->servers[i].is_mdns ? " mDNS" : "") : "", - IS_ENABLED(CONFIG_LLMNR_RESOLVER) ? - (ctx->servers[i].is_llmnr ? " LLMNR" : "") : "", + 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 ? iface_str : "");
idx++;
}
}
Expand Down Expand Up @@ -441,14 +499,40 @@

ctx->servers[i].sock = ret;

/* Try to bind to the interface if it is set */
if (ctx->servers[i].if_index > 0) {
ret = bind_to_iface(ctx->servers[i].sock,
&ctx->servers[i].dns_server,
ctx->servers[i].if_index);

Check notice on line 506 in subsys/net/lib/dns/resolve.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/dns/resolve.c:506 - ret = bind_to_iface(ctx->servers[i].sock, - &ctx->servers[i].dns_server, + ret = bind_to_iface(ctx->servers[i].sock, &ctx->servers[i].dns_server,
if (ret < 0) {
zsock_close(ctx->servers[i].sock);
ctx->servers[i].sock = -1;
continue;
}

iface = net_if_get_by_index(ctx->servers[i].if_index);
NET_DBG("Binding %s to %d",
net_sprint_addr(ctx->servers[i].dns_server.sa_family,
&net_sin(&ctx->servers[i].dns_server)->sin_addr),
ctx->servers[i].if_index);
} else {
iface = NULL;
}

if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
iface = net_if_ipv6_select_src_iface(
if (iface == NULL) {
iface = net_if_ipv6_select_src_iface(
&net_sin6(&ctx->servers[i].dns_server)->sin6_addr);
}

addr6 = net_if_ipv6_select_src_addr(iface,
&net_sin6(&ctx->servers[i].dns_server)->sin6_addr);
} else {
iface = net_if_ipv4_select_src_iface(
if (iface == NULL) {
iface = net_if_ipv4_select_src_iface(
&net_sin(&ctx->servers[i].dns_server)->sin_addr);
}

addr4 = net_if_ipv4_select_src_addr(iface,
&net_sin(&ctx->servers[i].dns_server)->sin_addr);
}
Expand Down
41 changes: 34 additions & 7 deletions subsys/net/lib/shell/dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(net_shell);

#include <zephyr/net/socket.h>
#include <zephyr/net/dns_resolve.h>

#include "net_shell_private.h"
Expand Down Expand Up @@ -59,29 +60,55 @@
PR_WARNING("dns: Unhandled status %d received\n", status);
}

static const char *printable_iface(const char *iface_name,
const char *found,
const char *not_found)
{

Check notice on line 66 in subsys/net/lib/shell/dns.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/shell/dns.c:66 -static const char *printable_iface(const char *iface_name, - const char *found, - const char *not_found) +static const char *printable_iface(const char *iface_name, const char *found, const char *not_found)
if (iface_name[0] != '\0') {
return found;
}

return not_found;
}

static void print_dns_info(const struct shell *sh,
struct dns_resolve_context *ctx)
{
int i;
int i, ret;

PR("DNS servers:\n");

for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS +
DNS_MAX_MCAST_SERVERS; i++) {
char iface_name[IFNAMSIZ] = { 0 };

if (ctx->servers[i].if_index > 0) {
ret = net_if_get_name(
net_if_get_by_index(ctx->servers[i].if_index),
iface_name, sizeof(iface_name));
if (ret < 0) {

Check notice on line 89 in subsys/net/lib/shell/dns.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/shell/dns.c:89 - char iface_name[IFNAMSIZ] = { 0 }; + char iface_name[IFNAMSIZ] = {0}; if (ctx->servers[i].if_index > 0) { - ret = net_if_get_name( - net_if_get_by_index(ctx->servers[i].if_index), - iface_name, sizeof(iface_name)); + ret = net_if_get_name(net_if_get_by_index(ctx->servers[i].if_index), + iface_name, sizeof(iface_name));
snprintk(iface_name, sizeof(iface_name), "%d",
ctx->servers[i].if_index);
}
}

if (ctx->servers[i].dns_server.sa_family == AF_INET) {
PR("\t%s:%u\n",
PR("\t%s:%u%s%s\n",
net_sprint_ipv4_addr(
&net_sin(&ctx->servers[i].dns_server)->
sin_addr),
ntohs(net_sin(
&ctx->servers[i].dns_server)->sin_port));
ntohs(net_sin(&ctx->servers[i].dns_server)->sin_port),
printable_iface(iface_name, " via ", ""),
printable_iface(iface_name, iface_name, ""));

} else if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
PR("\t[%s]:%u\n",
PR("\t[%s]:%u%s%s\n",
net_sprint_ipv6_addr(
&net_sin6(&ctx->servers[i].dns_server)->
sin6_addr),
ntohs(net_sin6(
&ctx->servers[i].dns_server)->sin6_port));
ntohs(net_sin6(&ctx->servers[i].dns_server)->sin6_port),

Check notice on line 109 in subsys/net/lib/shell/dns.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/shell/dns.c:109 - net_sprint_ipv4_addr( - &net_sin(&ctx->servers[i].dns_server)-> - sin_addr), + net_sprint_ipv4_addr(&net_sin(&ctx->servers[i].dns_server)->sin_addr), ntohs(net_sin(&ctx->servers[i].dns_server)->sin_port), printable_iface(iface_name, " via ", ""), printable_iface(iface_name, iface_name, "")); } else if (ctx->servers[i].dns_server.sa_family == AF_INET6) { PR("\t[%s]:%u%s%s\n", - net_sprint_ipv6_addr( - &net_sin6(&ctx->servers[i].dns_server)-> - sin6_addr), + net_sprint_ipv6_addr(&net_sin6(&ctx->servers[i].dns_server)->sin6_addr),
printable_iface(iface_name, " via ", ""),
printable_iface(iface_name, iface_name, ""));
}
}

Expand Down
15 changes: 15 additions & 0 deletions tests/net/utils/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,21 @@
},
.verdict = true
},
{
.address = "192.0.2.3:80/foobar",
.len = sizeof("192.0.2.3:80") - 1,
.result = {
.sin_family = AF_INET,
.sin_port = htons(80),
.sin_addr = {
.s4_addr[0] = 192,
.s4_addr[1] = 0,
.s4_addr[2] = 2,
.s4_addr[3] = 3
}
},
.verdict = true
},
{
.address = "192.0.2.3/foobar",
.len = sizeof("192.0.2.3/foobar") - 1,
Expand Down Expand Up @@ -566,7 +581,7 @@
.address = "a.b.c.d",
.verdict = false
},
};

Check notice on line 584 in tests/net/utils/src/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

tests/net/utils/src/main.c:584 - { - .address = "192.0.2.1:80", - .len = sizeof("192.0.2.1:80") - 1, - .result = { - .sin_family = AF_INET, - .sin_port = htons(80), - .sin_addr = { - .s4_addr[0] = 192, - .s4_addr[1] = 0, - .s4_addr[2] = 2, - .s4_addr[3] = 1 - } - }, - .verdict = true - }, - { - .address = "192.0.2.2", - .len = sizeof("192.0.2.2") - 1, - .result = { - .sin_family = AF_INET, - .sin_port = 0, - .sin_addr = { - .s4_addr[0] = 192, - .s4_addr[1] = 0, - .s4_addr[2] = 2, - .s4_addr[3] = 2 - } - }, - .verdict = true - }, - { - .address = "192.0.2.3/foobar", - .len = sizeof("192.0.2.3/foobar") - 8, - .result = { - .sin_family = AF_INET, - .sin_port = 0, - .sin_addr = { - .s4_addr[0] = 192, - .s4_addr[1] = 0, - .s4_addr[2] = 2, - .s4_addr[3] = 3 - } - }, - .verdict = true - }, - { - .address = "255.255.255.255:0", - .len = sizeof("255.255.255.255:0") - 1, - .result = { - .sin_family = AF_INET, - .sin_port = 0, - .sin_addr = { - .s4_addr[0] = 255, - .s4_addr[1] = 255, - .s4_addr[2] = 255, - .s4_addr[3] = 255 - } - }, - .verdict = true - }, - { - .address = "127.0.0.42:65535", - .len = sizeof("127.0.0.42:65535") - 1, - .result = { - .sin_family = AF_INET, - .sin_port = htons(65535), - .sin_addr = { - .s4_addr[0] = 127, - .s4_addr[1] = 0, - .s4_addr[2] = 0, - .s4_addr[3] = 42 - } - }, - .verdict = true - }, - { - .address = "192.0.2.3:80/foobar", - .len = sizeof("192.0.2.3:80/foobar") - 1, - .verdict = false - }, - { - .address = "192.168.1.1:65536/foobar", - .len = sizeof("192.168.1.1:65536") - 1, - .verdict = false - }, - { - .address = "192.0.2.3:80/foobar", - .len = sizeof("192.0.2.3") - 1, - .result = { - .sin_family = AF_INET, - .sin_port = 0, - .sin_addr = { - .s4_addr[0] = 192, - .s4_addr[1] = 0, - .s4_addr[2] = 2, - .s4_addr[3] = 3 - } - }, - .verdict = true - }, - { - .address = "192.0.2.3:80/foobar", - .len = sizeof("192.0.2.3:80") - 1, - .result = { - .sin_family = AF_INET, - .sin_port = htons(80), - .sin_addr = { - .s4_addr[0] = 192, - .s4_addr[1] = 0, - .s4_addr[2] = 2, - .s4_addr[3] = 3 - } - }, - .verdict = true - }, - { - .address = "192.0.2.3/foobar", - .len = sizeof("192.0.2.3/foobar") - 1, - .verdict = false - }, - { - .address = "192.0.2.3:80:80", - .len = sizeof("192.0.2.3:80:80") - 1, - .verdict = false - }, - { - .address = "192.0.2.1:80000", - .len = sizeof("192.0.2.1:80000") - 1, - .verdict = false - }, - { - .address = "192.168.0.1", - .len = sizeof("192.168.0.1:80000") - 1, - .result = { - .sin_family = AF_INET, - .sin_port = 0, - .sin_addr = { - .s4_addr[0] = 192, - .s4_addr[1] = 168, - .s4_addr[2] = 0, - .s4_addr[3] = 1 - } - }, - .verdict = true - }, - { - .address = "a.b.c.d", - .verdict = false - }, + {.address = "192.0.2.1:80", + .len = sizeof("192.0.2.1:80") - 1, + .result = {.sin_family = AF_INET, + .sin_port = htons(80), + .sin_addr = {.s4_addr[0] = 192, + .s4_addr[1] = 0, + .s4_addr[2] = 2, + .s4_addr[3] = 1}}, + .verdict = true}, + {.address = "192.0.2.2", + .len = sizeof("192.0.2.2") - 1, + .result = {.sin_family = AF_INET, + .sin_port = 0, + .sin_addr = {.s4_addr[0] = 192, + .s4_addr[1] = 0, + .s4_addr[2] = 2, + .s4_addr[3] = 2}}, + .verdict = true}, + {.address = "192.0.2.3/foobar", + .len = sizeof("192.0.2.3/foobar") - 8, + .result = {.sin_family = AF_INET, + .sin_port = 0, + .sin_addr = {.s4_addr[0] = 192, + .s4_addr[1] = 0, + .s4_addr[2] = 2, + .s4_addr[3] = 3}}, + .verdict = true}, + {.address = "255.255.255.255:0", + .len = sizeof("255.255.255.255:0") - 1, + .result = {.sin_family = AF_INET, + .sin_port = 0, + .sin_addr = {.s4_addr[0] = 255, + .s4_addr[1] = 255, + .s4_addr[2] = 255, +
#endif
#if defined(CONFIG_NET_IPV6)
static const struct {
Expand Down
Loading