[PATCH] net: introduce CONFIG_DNS

Jerome Forissier jerome.forissier at linaro.org
Mon Jul 21 15:46:04 CEST 2025


Hi E,

On 7/19/25 06:20, E Shattow wrote:
> There is a crash with ping command: I apply the patch and enable
> CONFIG_DNS for a build of starfive_visionfive2_defconfig on Pine64
> Star64 board.
> 
> # ping invalid
> 
> ethernet at 16030000 Waiting for PHY auto negotiation to complete....... done
> No valid name server (dnsip/dnsip2)
> ping - send ICMP ECHO_REQUEST to network host
> 
> Usage:
> ping pingAddressOrHostName
> 
> # dhcp
> DHCP client bound to address N.N.N.N (31 ms)
> 
> # ping invalid
> 
> Unhandled exception: Load access fault
> EPC: 00000000fffa365a RA: 00000000fffafa92 TVAL: 0000000000000000
> EPC: 000000004026e65a RA: 000000004027aa92 reloc adjusted
> 
> SP:  00000000ff717b90 GP:  00000000ff724e40 TP:  0000000000000003
> T0:  00000000ff717ce4 T1:  fffffffffe02a8c0 T2:  0000000000000007
> S0:  00000000ff717e38 S1:  0000000000000000 A0:  0000000000000000
> A1:  00000000ffffd648 A2:  0000000000000010 A3:  0000000000000000
> A4:  00000000fffafa80 A5:  0000000000000000 A6:  0000000000000001
> A7:  0000000000000001 S2:  0000000000000000 S3:  0000000000000019
> S4:  0000000000010000 S5:  00000000fffb0f48 S6:  00000000000000c0
> S7:  00000000ffffd428 S8:  0000000000000000 S9:  0000000000000000
> S10: 00000000ff737db0 S11: 0000000000000001 T3:  00000000ff737e10
> T4:  0000000000000035 T5:  ffffffffffffffff T6:  00000000ff717ce0
> 
> Code: 171b 0187 969b 0106 8f55 bfe9 4501 b749 (411c)

Not reproducible here, neither on arm64 QEMU nor ZynqMP KV260.

----------------------------------
$ grep -E -e NET_LWIP -e _DNS .config
# CONFIG_CMD_DNS is not set
CONFIG_NET_LWIP=y
CONFIG_PROT_DNS_LWIP=y
CONFIG_DNS=y
----------------------------------
ZynqMP> ping invalid
No valid name server (dnsip/dnsip2)
ping - send ICMP ECHO_REQUEST to network host

Usage:
ping pingAddressOrHostName
ZynqMP> dhcp
DHCP client bound to address 192.168.0.12 (2047 ms)
ZynqMP> ping invalid
DNS: host not found
ping - send ICMP ECHO_REQUEST to network host

Usage:
ping pingAddressOrHostName
----------------------------------

Could you please debug further on you platform and point me to what's
going wrong?

> 
> On 7/18/25 03:48, Jerome Forissier wrote:
>> Introduce the DNS Kconfig symbol so that various network commands may
>> use host names without the dns command (CMD_DNS) being selected.
>>
>> Signed-off-by: Jerome Forissier <jerome.forissier at linaro.org>
>> CC: E Shattow <e at freeshell.de>
>> ---
>>
>>  cmd/Kconfig            |   2 +-
>>  cmd/lwip/dns.c         | 108 ---------------------------------------
>>  doc/usage/cmd/sntp.rst |   8 +--
>>  doc/usage/cmd/wget.rst |   2 +-
>>  include/net-legacy.h   |   2 +-
>>  net/Kconfig            |   8 ++-
>>  net/Makefile           |   2 +-
>>  net/lwip/Makefile      |   1 +
>>  net/lwip/dns.c         | 113 +++++++++++++++++++++++++++++++++++++++++
>>  net/lwip/net-lwip.c    |   6 +--
>>  net/net.c              |  10 ++--
>>  net/wget.c             |   2 +-
>>  12 files changed, 138 insertions(+), 126 deletions(-)
>>  create mode 100644 net/lwip/dns.c
>>
>> diff --git a/cmd/Kconfig b/cmd/Kconfig
>> index b3b5be1ea79..7a9c4ddb215 100644
>> --- a/cmd/Kconfig
>> +++ b/cmd/Kconfig
>> @@ -2110,7 +2110,7 @@ config CMD_DHCP
>>  
>>  config CMD_DNS
>>  	bool "dns"
>> -	select PROT_DNS_LWIP if NET_LWIP
>> +	select DNS
>>  	help
>>  	  Lookup the IP of a hostname
>>  
>> diff --git a/cmd/lwip/dns.c b/cmd/lwip/dns.c
>> index b5fccc7433e..3eb698b3f82 100644
>> --- a/cmd/lwip/dns.c
>> +++ b/cmd/lwip/dns.c
>> @@ -2,115 +2,7 @@
>>  /* Copyright (C) 2024 Linaro Ltd. */
>>  
>>  #include <command.h>
>> -#include <console.h>
>> -#include <env.h>
>> -#include <lwip/dns.h>
>> -#include <lwip/timeouts.h>
>>  #include <net.h>
>> -#include <time.h>
>>  
>>  U_BOOT_CMD(dns, 3, 1, do_dns, "lookup the IP of a hostname",
>>  	   "hostname [envvar]");
>> -
>> -#define DNS_RESEND_MS 1000
>> -#define DNS_TIMEOUT_MS 10000
>> -
>> -struct dns_cb_arg {
>> -	ip_addr_t host_ipaddr;
>> -	const char *var;
>> -	bool done;
>> -};
>> -
>> -static void do_dns_tmr(void *arg)
>> -{
>> -	dns_tmr();
>> -}
>> -
>> -static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
>> -{
>> -	struct dns_cb_arg *dns_cb_arg = arg;
>> -	char *ipstr = ip4addr_ntoa(ipaddr);
>> -
>> -	dns_cb_arg->done = true;
>> -
>> -	if (!ipaddr) {
>> -		printf("DNS: host not found\n");
>> -		dns_cb_arg->host_ipaddr.addr = 0;
>> -		return;
>> -	}
>> -
>> -	dns_cb_arg->host_ipaddr.addr = ipaddr->addr;
>> -
>> -	if (dns_cb_arg->var)
>> -		env_set(dns_cb_arg->var, ipstr);
>> -}
>> -
>> -static int dns_loop(struct udevice *udev, const char *name, const char *var)
>> -{
>> -	struct dns_cb_arg dns_cb_arg = { };
>> -	struct netif *netif;
>> -	ip_addr_t ipaddr;
>> -	ulong start;
>> -	int ret;
>> -
>> -	dns_cb_arg.var = var;
>> -
>> -	netif = net_lwip_new_netif(udev);
>> -	if (!netif)
>> -		return CMD_RET_FAILURE;
>> -
>> -	if (net_lwip_dns_init()) {
>> -		net_lwip_remove_netif(netif);
>> -		return CMD_RET_FAILURE;
>> -	}
>> -
>> -	dns_cb_arg.done = false;
>> -
>> -	ret = dns_gethostbyname(name, &ipaddr, dns_cb, &dns_cb_arg);
>> -
>> -	if (ret == ERR_OK) {
>> -		dns_cb(name, &ipaddr, &dns_cb_arg);
>> -	} else if (ret == ERR_INPROGRESS) {
>> -		start = get_timer(0);
>> -		sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
>> -		do {
>> -			net_lwip_rx(udev, netif);
>> -			if (dns_cb_arg.done)
>> -				break;
>> -			if (ctrlc()) {
>> -				printf("\nAbort\n");
>> -				break;
>> -			}
>> -		} while (get_timer(start) < DNS_TIMEOUT_MS);
>> -		sys_untimeout(do_dns_tmr, NULL);
>> -	}
>> -
>> -	net_lwip_remove_netif(netif);
>> -
>> -	if (dns_cb_arg.done && dns_cb_arg.host_ipaddr.addr != 0) {
>> -		if (!var)
>> -			printf("%s\n", ipaddr_ntoa(&ipaddr));
>> -		return CMD_RET_SUCCESS;
>> -	}
>> -
>> -	return CMD_RET_FAILURE;
>> -}
>> -
>> -int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> -{
>> -	char *name;
>> -	char *var = NULL;
>> -
>> -	if (argc == 1 || argc > 3)
>> -		return CMD_RET_USAGE;
>> -
>> -	name = argv[1];
>> -
>> -	if (argc == 3)
>> -		var = argv[2];
>> -
>> -	if (net_lwip_eth_start() < 0)
>> -		return CMD_RET_FAILURE;
>> -
>> -	return dns_loop(eth_get_dev(), name, var);
>> -}
>> diff --git a/doc/usage/cmd/sntp.rst b/doc/usage/cmd/sntp.rst
>> index d97f83053f7..2046828130d 100644
>> --- a/doc/usage/cmd/sntp.rst
>> +++ b/doc/usage/cmd/sntp.rst
>> @@ -12,7 +12,7 @@ Synopsis
>>  ::
>>  
>>      sntp [serverip]
>> -    sntp [servername]  # NET_LWIP=y && CMD_DNS=y only
>> +    sntp [servername]  # NET_LWIP=y && DNS=y only
>>  
>>  
>>  Description
>> @@ -27,8 +27,8 @@ The address of the NTP server does not need to be given if the DHCP server
>>  provides one. The legacy network stack (`CONFIG_NET=y`) can only use the
>>  first NTP server provided in the `ntp-servers` DHCP option.
>>  
>> -When the network stack is lwIP (`CONFIG_NET_LWIP=y`) and the dns command
>> -is enabled (`CONFIG_CMD_DNS=y`), then the sntp command accepts a server
>> +When the network stack is lwIP (`CONFIG_NET_LWIP=y`) and DNS resolution
>> +is enabled (`CONFIG_DNS=y`), then the sntp command accepts a server
>>  name as an argument.
>>  
>>  The network time is sent as UTC. So, if you want to set the RTC to any local
>> @@ -61,7 +61,7 @@ Examples
>>      => date
>>      Date: 2025-06-16 (Monday)    Time: 17:19:57
>>  
>> -With `CONFIG_NET_LWIP=y` and `CONFIG_CMD_DNS=y`:
>> +With `CONFIG_NET_LWIP=y` and `CONFIG_DNS=y`:
>>  
>>  ::
>>  
>> diff --git a/doc/usage/cmd/wget.rst b/doc/usage/cmd/wget.rst
>> index 06df2842549..8feda0248b2 100644
>> --- a/doc/usage/cmd/wget.rst
>> +++ b/doc/usage/cmd/wget.rst
>> @@ -38,7 +38,7 @@ address
>>      memory address for the data downloaded
>>  
>>  host
>> -    IP address (or host name if `CONFIG_CMD_DNS` is enabled) of the HTTP
>> +    IP address (or host name if `CONFIG_DNS` is enabled) of the HTTP
>>      server, defaults to the value of environment variable *serverip*.
>>  
>>  path
>> diff --git a/include/net-legacy.h b/include/net-legacy.h
>> index a7dbcec1506..7ba5148a75a 100644
>> --- a/include/net-legacy.h
>> +++ b/include/net-legacy.h
>> @@ -316,7 +316,7 @@ extern u32	net_boot_file_size;
>>  /* Boot file size in blocks as reported by the DHCP server */
>>  extern u32	net_boot_file_expected_size_in_blocks;
>>  
>> -#if defined(CONFIG_CMD_DNS)
>> +#if defined(CONFIG_DNS)
>>  extern char *net_dns_resolve;		/* The host to resolve  */
>>  extern char *net_dns_env_var;		/* the env var to put the ip into */
>>  #endif
>> diff --git a/net/Kconfig b/net/Kconfig
>> index 24508026200..40ec6bbce76 100644
>> --- a/net/Kconfig
>> +++ b/net/Kconfig
>> @@ -244,11 +244,17 @@ config NET_RANDOM_ETHADDR
>>  	  generated. It will be saved to the appropriate environment variable,
>>  	  too.
>>  
>> +config DNS
>> +	bool "Enable DNS resolutions"
>> +	select PROT_DNS_LWIP if NET_LWIP
>> +	help
>> +	  Selecting this will allow the network stack to use server names
>> +	  in addition to IP addresses.
>> +
> 
> Perhaps instead of CONFIG_DNS then the CONFIG_NET_DNS_LWIP symbol? or
> CONFIG_NET_DNS if it will coexist with both legacy network stack and
> LwIP.

CONFIG_DNS is indeed targeted at NET_LWIP and legacy NET as well. That is,
regardless of NET vs NET_LWIP, one should be able to disable CMD_DNS and
still have DNS support in the other commands.

I do not think CONFIG_NET_DNS is better than CONFIG_DNS. The shorter the
Kconfig symbols the better (to some extent of course). It is quite obvious
that DNS is a network thing.

> That is unless you foresee a build of U-Boot without any
> networking support but having CONFIG_DNS symbol as a requisite for tools
> that do DNS certificate processing i.e.

No, no, if this kind of need arises we will find a suitable Kconfig symbol
I'm sure.

> If DHCP is likewise separated out you might not need the 'dhcp' command
> as in for EFI but still using the protocol.

Makes sense.

> I'm not sure why you want to
> add a CONFIG_DNS instead of just exposing the protocol symbols,

Because lwIP does have a protocol symbol (CONFIG_PROT_DNS_LWIP) but the
legacy NET does not. CONFIG_PROT_DNS_LWIP is just a clean way to set
a couple of defines for lwIP internal use (LWIP_DNS and DNS_TABLE_SIZE).

> unless,
> there are topical things or situations where portions of supporting code
> are needed without the presence of networking.
> 
>>  config WGET
>>  	bool "Enable wget"
>>  	select PROT_TCP if NET
>>  	select PROT_TCP_LWIP if NET_LWIP
>> -	select PROT_DNS_LWIP if NET_LWIP
>>  	help
>>  	  Selecting this will enable wget, an interface to send HTTP requests
>>  	  via the network stack.
>> diff --git a/net/Makefile b/net/Makefile
>> index d63f62b7c8a..468820186cf 100644
>> --- a/net/Makefile
>> +++ b/net/Makefile
>> @@ -10,7 +10,7 @@ ifeq ($(CONFIG_NET),y)
>>  obj-$(CONFIG_NET)      += arp.o
>>  obj-$(CONFIG_CMD_BOOTP) += bootp.o
>>  obj-$(CONFIG_CMD_CDP)  += cdp.o
>> -obj-$(CONFIG_CMD_DNS)  += dns.o
>> +obj-$(CONFIG_DNS)  += dns.o
>>  obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
>>  obj-$(CONFIG_IPV6)     += ndisc.o
>>  obj-$(CONFIG_$(PHASE_)DM_ETH) += net.o
>> diff --git a/net/lwip/Makefile b/net/lwip/Makefile
>> index 97299d9b542..90d3300bd12 100644
>> --- a/net/lwip/Makefile
>> +++ b/net/lwip/Makefile
>> @@ -2,6 +2,7 @@ ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
>>  
>>  obj-$(CONFIG_$(PHASE_)DM_ETH) += net-lwip.o
>>  obj-$(CONFIG_CMD_DHCP) += dhcp.o
>> +obj-$(CONFIG_DNS) += dns.o
>>  obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
>>  obj-$(CONFIG_WGET) += wget.o
>>  
>> diff --git a/net/lwip/dns.c b/net/lwip/dns.c
>> new file mode 100644
>> index 00000000000..9964003195f
>> --- /dev/null
>> +++ b/net/lwip/dns.c
>> @@ -0,0 +1,113 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/* Copyright (C) 2024 Linaro Ltd. */
>> +
>> +#include <command.h>
>> +#include <console.h>
>> +#include <env.h>
>> +#include <lwip/dns.h>
>> +#include <lwip/timeouts.h>
>> +#include <net.h>
>> +#include <time.h>
>> +
>> +#define DNS_RESEND_MS 1000
>> +#define DNS_TIMEOUT_MS 10000
>> +
>> +struct dns_cb_arg {
>> +	ip_addr_t host_ipaddr;
>> +	const char *var;
>> +	bool done;
>> +};
>> +
>> +static void do_dns_tmr(void *arg)
>> +{
>> +	dns_tmr();
>> +}
>> +
>> +static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
>> +{
>> +	struct dns_cb_arg *dns_cb_arg = arg;
>> +	char *ipstr = ip4addr_ntoa(ipaddr);
>> +
>> +	dns_cb_arg->done = true;
>> +
>> +	if (!ipaddr) {
>> +		printf("DNS: host not found\n");
>> +		dns_cb_arg->host_ipaddr.addr = 0;
>> +		return;
>> +	}
>> +
>> +	dns_cb_arg->host_ipaddr.addr = ipaddr->addr;
>> +
>> +	if (dns_cb_arg->var)
>> +		env_set(dns_cb_arg->var, ipstr);
>> +}
>> +
>> +static int dns_loop(struct udevice *udev, const char *name, const char *var)
>> +{
>> +	struct dns_cb_arg dns_cb_arg = { };
>> +	struct netif *netif;
>> +	ip_addr_t ipaddr;
>> +	ulong start;
>> +	int ret;
>> +
>> +	dns_cb_arg.var = var;
>> +
>> +	netif = net_lwip_new_netif(udev);
>> +	if (!netif)
>> +		return CMD_RET_FAILURE;
>> +
>> +	if (net_lwip_dns_init()) {
>> +		net_lwip_remove_netif(netif);
>> +		return CMD_RET_FAILURE;
>> +	}
>> +
>> +	dns_cb_arg.done = false;
>> +
>> +	ret = dns_gethostbyname(name, &ipaddr, dns_cb, &dns_cb_arg);
>> +
>> +	if (ret == ERR_OK) {
>> +		dns_cb(name, &ipaddr, &dns_cb_arg);
>> +	} else if (ret == ERR_INPROGRESS) {
>> +		start = get_timer(0);
>> +		sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
>> +		do {
>> +			net_lwip_rx(udev, netif);
>> +			if (dns_cb_arg.done)
>> +				break;
>> +			if (ctrlc()) {
>> +				printf("\nAbort\n");
>> +				break;
>> +			}
>> +		} while (get_timer(start) < DNS_TIMEOUT_MS);
>> +		sys_untimeout(do_dns_tmr, NULL);
>> +	}
>> +
>> +	net_lwip_remove_netif(netif);
>> +
>> +	if (dns_cb_arg.done && dns_cb_arg.host_ipaddr.addr != 0) {
>> +		if (!var)
>> +			printf("%s\n", ipaddr_ntoa(&ipaddr));
>> +		return CMD_RET_SUCCESS;
>> +	}
>> +
>> +	return CMD_RET_FAILURE;
>> +}
>> +
>> +int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> +{
>> +	char *name;
>> +	char *var = NULL;
>> +
>> +	if (argc == 1 || argc > 3)
>> +		return CMD_RET_USAGE;
>> +
>> +	name = argv[1];
>> +
>> +	if (argc == 3)
>> +		var = argv[2];
>> +
>> +	if (net_lwip_eth_start() < 0)
>> +		return CMD_RET_FAILURE;
>> +
>> +	return dns_loop(eth_get_dev(), name, var);
>> +}
>> diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c
>> index 3918d57d7e5..7069e56065f 100644
>> --- a/net/lwip/net-lwip.c
>> +++ b/net/lwip/net-lwip.c
>> @@ -147,7 +147,7 @@ static int get_udev_ipv4_info(struct udevice *dev, ip4_addr_t *ip,
>>   */
>>  int net_lwip_dns_init(void)
>>  {
>> -#if CONFIG_IS_ENABLED(CMD_DNS)
>> +#if CONFIG_IS_ENABLED(DNS)
>>  	bool has_server = false;
>>  	ip_addr_t ns;
>>  	char *nsenv;
>> @@ -369,7 +369,7 @@ int net_lwip_rx(struct udevice *udev, struct netif *netif)
>>   */
>>  int net_lwip_dns_resolve(char *name_or_ip, ip_addr_t *ip)
>>  {
>> -#if defined(CONFIG_CMD_DNS)
>> +#if defined(CONFIG_DNS)
>>  	char *var = "_dnsres";
>>  	char *argv[] = { "dns", name_or_ip, var, NULL };
>>  	int argc = ARRAY_SIZE(argv) - 1;
>> @@ -378,7 +378,7 @@ int net_lwip_dns_resolve(char *name_or_ip, ip_addr_t *ip)
>>  	if (ipaddr_aton(name_or_ip, ip))
>>  		return 0;
>>  
>> -#if defined(CONFIG_CMD_DNS)
>> +#if defined(CONFIG_DNS)
>>  	if (do_dns(NULL, 0, argc, argv) != CMD_RET_SUCCESS)
>>  		return -1;
>>  
>> diff --git a/net/net.c b/net/net.c
>> index 5219367e391..382a27e0a77 100644
>> --- a/net/net.c
>> +++ b/net/net.c
>> @@ -115,7 +115,7 @@
>>  #include "bootp.h"
>>  #include "cdp.h"
>>  #include "dhcpv6.h"
>> -#if defined(CONFIG_CMD_DNS)
>> +#if defined(CONFIG_DNS)
>>  #include "dns.h"
>>  #endif
>>  #include "link_local.h"
>> @@ -288,7 +288,7 @@ static int on_vlan(const char *name, const char *value, enum env_op op,
>>  }
>>  U_BOOT_ENV_CALLBACK(vlan, on_vlan);
>>  
>> -#if defined(CONFIG_CMD_DNS)
>> +#if defined(CONFIG_DNS)
>>  static int on_dnsip(const char *name, const char *value, enum env_op op,
>>  	int flags)
>>  {
>> @@ -582,7 +582,7 @@ restart:
>>  			nc_start();
>>  			break;
>>  #endif
>> -#if defined(CONFIG_CMD_DNS)
>> +#if defined(CONFIG_DNS)
>>  		case DNS:
>>  			dns_start();
>>  			break;
>> @@ -1507,7 +1507,7 @@ static int net_check_prereq(enum proto_t protocol)
>>  		}
>>  		goto common;
>>  #endif
>> -#if defined(CONFIG_CMD_DNS)
>> +#if defined(CONFIG_DNS)
>>  	case DNS:
>>  		if (net_dns_server.s_addr == 0) {
>>  			puts("*** ERROR: DNS server address not given\n");
>> @@ -1540,7 +1540,7 @@ static int net_check_prereq(enum proto_t protocol)
>>  			return 1;
>>  		}
>>  #if	defined(CONFIG_CMD_PING) || \
>> -	defined(CONFIG_CMD_DNS) || defined(CONFIG_PROT_UDP)
>> +	defined(CONFIG_DNS) || defined(CONFIG_PROT_UDP)
>>  common:
>>  #endif
>>  		/* Fall through */
>> diff --git a/net/wget.c b/net/wget.c
>> index 3c0fff488eb..e65ce15ccb3 100644
>> --- a/net/wget.c
>> +++ b/net/wget.c
>> @@ -393,7 +393,7 @@ int wget_do_request(ulong dst_addr, char *uri)
>>  	if (string_to_ip(host_name).s_addr) {
>>  		s = host_name;
>>  	} else {
>> -#if IS_ENABLED(CONFIG_CMD_DNS)
>> +#if IS_ENABLED(CONFIG_DNS)
>>  		net_dns_resolve = host_name;
>>  		net_dns_env_var = "httpserverip";
>>  		if (net_loop(DNS) < 0) {
> 
> If hostnames are valid then it does appear to be working for commands
> ping and wget. I do not think there was a crash for wget.

OK. Thanks for testing.

> 
> best regards,
> 
> -E Shattow

Regards,
-- 
Jerome


More information about the U-Boot mailing list