From 0e5674c77fbd52f7789696f603a1ca98c4dac77e Mon Sep 17 00:00:00 2001 From: nuttxs Date: Thu, 6 Nov 2025 11:11:15 +0800 Subject: [PATCH] netutils/netlib: support delete the DNS server address by index or address - Modify the DHCP-client data structure to support multiple DNS addresses - Enhance DHCP-option parsing to extract all DNS-server addresses - Set all received DNS-server addresses - fix some test case build error Signed-off-by: nuttxs --- examples/bridge/bridge_main.c | 26 ++++++- examples/discover/discover_main.c | 13 +++- examples/tcpecho/tcpecho_main.c | 13 +++- examples/webserver/webserver_main.c | 13 +++- examples/xmlrpc/xmlrpc_main.c | 14 +++- include/netutils/dhcpc.h | 3 +- include/netutils/netlib.h | 4 + netutils/dhcpc/dhcpc.c | 48 ++++++++++-- netutils/netlib/CMakeLists.txt | 4 +- netutils/netlib/Makefile | 4 +- netutils/netlib/netlib_delipv4dnsaddr.c | 97 +++++++++++++++++++++++++ netutils/netlib/netlib_delipv6dnsaddr.c | 97 +++++++++++++++++++++++++ netutils/netlib/netlib_obtainipv4addr.c | 20 +++-- 13 files changed, 326 insertions(+), 30 deletions(-) create mode 100644 netutils/netlib/netlib_delipv4dnsaddr.c create mode 100644 netutils/netlib/netlib_delipv6dnsaddr.c diff --git a/examples/bridge/bridge_main.c b/examples/bridge/bridge_main.c index 2893c01c4d8..8d2165514e7 100644 --- a/examples/bridge/bridge_main.c +++ b/examples/bridge/bridge_main.c @@ -81,6 +81,7 @@ static int briget_net1_setup(void) struct dhcpc_state ds; void *handle; char inetaddr[INET_ADDRSTRLEN]; + int ret; #endif printf("NET1: Configuring %s\n", CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME); @@ -162,9 +163,17 @@ static int briget_net1_setup(void) &ds.default_router); } - if (ds.dnsaddr.s_addr != 0) + for (int i = 0; i < ds.num_dnsaddr; i++) { - netlib_set_ipv4dnsaddr(&ds.dnsaddr); + if (ds.dnsaddr[i].s_addr != 0) + { + ret = netlib_set_ipv4dnsaddr(&ds.dnsaddr[i]); + if (ret < 0) + { + nerr("NET1 ERROR: Set DNS server %d:%s address failed: %d\n", + i, inet_ntoa(ds.dnsaddr[i]), ret); + } + } } dhcpc_close(handle); @@ -213,6 +222,7 @@ static int briget_net2_setup(void) struct dhcpc_state ds; void *handle; char inetaddr[INET_ADDRSTRLEN]; + int ret; #endif printf("NET2: Configuring %s\n", CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME); @@ -288,9 +298,17 @@ static int briget_net2_setup(void) &ds.default_router); } - if (ds.dnsaddr.s_addr != 0) + for (int i = 0; i < ds.num_dnsaddr; i++) { - netlib_set_ipv4dnsaddr(&ds.dnsaddr); + if (ds.dnsaddr[i].s_addr != 0) + { + ret = netlib_set_ipv4dnsaddr(&ds.dnsaddr[i]); + if (ret < 0) + { + nerr("NET2 ERROR: Set DNS server %d:%s address failed: %d\n", + i, inet_ntoa(ds.dnsaddr[i]), ret); + } + } } dhcpc_close(handle); diff --git a/examples/discover/discover_main.c b/examples/discover/discover_main.c index ba81dbcb020..cd14720ed67 100644 --- a/examples/discover/discover_main.c +++ b/examples/discover/discover_main.c @@ -138,6 +138,7 @@ int main(int argc, FAR char *argv[]) { struct dhcpc_state ds; char inetaddr[INET_ADDRSTRLEN]; + int ret; dhcpc_request(handle, &ds); netlib_set_ipv4addr("eth0", &ds.ipaddr); @@ -152,9 +153,17 @@ int main(int argc, FAR char *argv[]) netlib_set_dripv4addr("eth0", &ds.default_router); } - if (ds.dnsaddr.s_addr != 0) + for (int i = 0; i < ds.num_dnsaddr; i++) { - netlib_set_ipv4dnsaddr(&ds.dnsaddr); + if (ds.dnsaddr[i].s_addr != 0) + { + ret = netlib_set_ipv4dnsaddr(&ds.dnsaddr[i]); + if (ret < 0) + { + nerr("ERROR: Set DNS server %d:%s address failed: %d\n", + i, inet_ntoa(ds.dnsaddr[i]), ret); + } + } } dhcpc_close(handle); diff --git a/examples/tcpecho/tcpecho_main.c b/examples/tcpecho/tcpecho_main.c index fac12f898c2..96aba809624 100644 --- a/examples/tcpecho/tcpecho_main.c +++ b/examples/tcpecho/tcpecho_main.c @@ -91,6 +91,7 @@ static int tcpecho_netsetup(void) struct dhcpc_state ds; void *handle; char inetaddr[INET_ADDRSTRLEN]; + int ret; #endif /* Many embedded network interfaces must have a software assigned MAC */ @@ -166,9 +167,17 @@ static int tcpecho_netsetup(void) netlib_set_dripv4addr("eth0", &ds.default_router); } - if (ds.dnsaddr.s_addr != 0) + for (int i = 0; i < ds.num_dnsaddr; i++) { - netlib_set_ipv4dnsaddr(&ds.dnsaddr); + if (ds.dnsaddr[i].s_addr != 0) + { + ret = netlib_set_ipv4dnsaddr(&ds.dnsaddr[i]); + if (ret < 0) + { + nerr("ERROR: Set DNS server %d:%s address failed: %d\n", + i, inet_ntoa(ds.dnsaddr[i]), ret); + } + } } dhcpc_close(handle); diff --git a/examples/webserver/webserver_main.c b/examples/webserver/webserver_main.c index d13b332eb36..7a16c8c4514 100644 --- a/examples/webserver/webserver_main.c +++ b/examples/webserver/webserver_main.c @@ -169,6 +169,7 @@ int main(int argc, FAR char *argv[]) { struct dhcpc_state ds; char inetaddr[INET_ADDRSTRLEN]; + int ret; dhcpc_request(handle, &ds); netlib_set_ipv4addr("eth0", &ds.ipaddr); @@ -183,9 +184,17 @@ int main(int argc, FAR char *argv[]) netlib_set_dripv4addr("eth0", &ds.default_router); } - if (ds.dnsaddr.s_addr != 0) + for (int i = 0; i < ds.num_dnsaddr; i++) { - netlib_set_ipv4dnsaddr(&ds.dnsaddr); + if (ds.dnsaddr[i].s_addr != 0) + { + ret = netlib_set_ipv4dnsaddr(&ds.dnsaddr[i]); + if (ret < 0) + { + nerr("ERROR: Set DNS server %d:%s address failed: %d\n", + i, inet_ntoa(ds.dnsaddr[i]), ret); + } + } } dhcpc_close(handle); diff --git a/examples/xmlrpc/xmlrpc_main.c b/examples/xmlrpc/xmlrpc_main.c index 2147e095f31..feeb0bf4ed6 100644 --- a/examples/xmlrpc/xmlrpc_main.c +++ b/examples/xmlrpc/xmlrpc_main.c @@ -41,6 +41,7 @@ * in the article at: http://www.drdobbs.com/web-development/\ * an-embeddable-lightweight-xml-rpc-server/184405364 */ + /* Lightweight Embedded XML-RPC Server main * * mtj@cogitollc.com @@ -334,6 +335,7 @@ static int xmlrpc_netinit(void) { struct dhcpc_state ds; char inetaddr[INET_ADDRSTRLEN]; + int ret; dhcpc_request(handle, &ds); netlib_set_ipv4addr("eth0", &ds.ipaddr); @@ -348,9 +350,17 @@ static int xmlrpc_netinit(void) netlib_set_dripv4addr("eth0", &ds.default_router); } - if (ds.dnsaddr.s_addr != 0) + for (int i = 0; i < ds.num_dnsaddr; i++) { - netlib_set_ipv4dnsaddr(&ds.dnsaddr); + if (ds.dnsaddr[i].s_addr != 0) + { + ret = netlib_set_ipv4dnsaddr(&ds.dnsaddr[i]); + if (ret < 0) + { + nerr("ERROR: Set DNS server %d:%s address failed: %d\n", + i, inet_ntoa(ds.dnsaddr[i]), ret); + } + } } dhcpc_close(handle); diff --git a/include/netutils/dhcpc.h b/include/netutils/dhcpc.h index 3529e554fe9..d55fca17045 100644 --- a/include/netutils/dhcpc.h +++ b/include/netutils/dhcpc.h @@ -55,7 +55,8 @@ struct dhcpc_state struct in_addr serverid; struct in_addr ipaddr; struct in_addr netmask; - struct in_addr dnsaddr; + struct in_addr dnsaddr[CONFIG_NETDB_DNSSERVER_NAMESERVERS]; + uint8_t num_dnsaddr; /* Number of DNS addresses received */ struct in_addr default_router; uint32_t lease_time; /* Lease expires in this number of seconds */ uint32_t renewal_time; /* Seconds to transition to RENEW state(T1) */ diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h index 2e816441f27..469bd046104 100644 --- a/include/netutils/netlib.h +++ b/include/netutils/netlib.h @@ -482,10 +482,14 @@ int netlib_ifdown(FAR const char *ifname); #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NETDB_DNSCLIENT) int netlib_set_ipv4dnsaddr(FAR const struct in_addr *inaddr); +int netlib_del_ipv4dnsaddr(FAR const struct in_addr *inaddr); +int netlib_del_ipv4dnsaddr_by_index(int index); #endif #if defined(CONFIG_NET_IPv6) && defined(CONFIG_NETDB_DNSCLIENT) int netlib_set_ipv6dnsaddr(FAR const struct in6_addr *inaddr); +int netlib_del_ipv6dnsaddr(FAR const struct in6_addr *inaddr); +int netlib_del_ipv6dnsaddr_by_index(int index); #endif int netlib_set_mtu(FAR const char *ifname, int mtu); diff --git a/netutils/dhcpc/dhcpc.c b/netutils/dhcpc/dhcpc.c index 3b0c2e19168..dc6b46230b3 100644 --- a/netutils/dhcpc/dhcpc.c +++ b/netutils/dhcpc/dhcpc.c @@ -378,11 +378,32 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult, case DHCP_OPTION_DNS_SERVER: - /* Get the DNS server address in network order */ + /* Get the DNS server addresses in network order. + * DHCP option 6 can contain multiple DNS server addresses, + * each 4 bytes long. + */ - if (optptr + 6 <= end) + if (optptr + 2 <= end) { - memcpy(&presult->dnsaddr.s_addr, optptr + 2, 4); + uint8_t optlen = *(optptr + 1); + uint8_t num_dns = optlen / 4; + uint8_t i; + + /* Limit to configured maximum */ + + if (num_dns > CONFIG_NETDB_DNSSERVER_NAMESERVERS) + { + num_dns = CONFIG_NETDB_DNSSERVER_NAMESERVERS; + } + + presult->num_dnsaddr = 0; + for (i = 0; i < num_dns && (optptr + 2 + i * 4 + 4) <= end; + i++) + { + memcpy(&presult->dnsaddr[i].s_addr, optptr + 2 + i * 4, + 4); + presult->num_dnsaddr++; + } } else { @@ -946,11 +967,22 @@ int dhcpc_request(FAR void *handle, FAR struct dhcpc_state *presult) ip4_addr2(presult->netmask.s_addr), ip4_addr3(presult->netmask.s_addr), ip4_addr4(presult->netmask.s_addr)); - ninfo("Got DNS server %u.%u.%u.%u\n", - ip4_addr1(presult->dnsaddr.s_addr), - ip4_addr2(presult->dnsaddr.s_addr), - ip4_addr3(presult->dnsaddr.s_addr), - ip4_addr4(presult->dnsaddr.s_addr)); + + /* Print all DNS servers received */ + + if (presult->num_dnsaddr > 0) + { + uint8_t i; + for (i = 0; i < presult->num_dnsaddr; i++) + { + ninfo("Got DNS server %d: %u.%u.%u.%u\n", i, + ip4_addr1(presult->dnsaddr[i].s_addr), + ip4_addr2(presult->dnsaddr[i].s_addr), + ip4_addr3(presult->dnsaddr[i].s_addr), + ip4_addr4(presult->dnsaddr[i].s_addr)); + } + } + ninfo("Got default router %u.%u.%u.%u\n", ip4_addr1(presult->default_router.s_addr), ip4_addr2(presult->default_router.s_addr), diff --git a/netutils/netlib/CMakeLists.txt b/netutils/netlib/CMakeLists.txt index d97307e6d03..66bc927a0e8 100644 --- a/netutils/netlib/CMakeLists.txt +++ b/netutils/netlib/CMakeLists.txt @@ -47,7 +47,7 @@ if(CONFIG_NETUTILS_NETLIB) endif() endif() if(CONFIG_NETDB_DNSCLIENT) - list(APPEND SRCS netlib_setipv4dnsaddr.c) + list(APPEND SRCS netlib_setipv4dnsaddr.c netlib_delipv4dnsaddr.c) endif() if(CONFIG_NET_ROUTE) list(APPEND SRCS netlib_ipv4route.c netlib_ipv4router.c) @@ -70,7 +70,7 @@ if(CONFIG_NETUTILS_NETLIB) list(APPEND SRCS netlib_autoconfig.c netlib_obtainipv6addr.c) endif() if(CONFIG_NETDB_DNSCLIENT) - list(APPEND SRCS netlib_setipv6dnsaddr.c) + list(APPEND SRCS netlib_setipv6dnsaddr.c netlib_delipv6dnsaddr.c) endif() if(CONFIG_NET_ROUTE) list(APPEND SRCS netlib_ipv6route.c netlib_ipv6router.c) diff --git a/netutils/netlib/Makefile b/netutils/netlib/Makefile index 93508ef859c..c590970e5b2 100644 --- a/netutils/netlib/Makefile +++ b/netutils/netlib/Makefile @@ -47,7 +47,7 @@ CSRCS += netlib_getarptab.c endif endif ifeq ($(CONFIG_NETDB_DNSCLIENT),y) -CSRCS += netlib_setipv4dnsaddr.c +CSRCS += netlib_setipv4dnsaddr.c netlib_delipv4dnsaddr.c endif ifeq ($(CONFIG_NET_ROUTE),y) CSRCS += netlib_ipv4route.c netlib_ipv4router.c @@ -71,7 +71,7 @@ CSRCS += netlib_autoconfig.c CSRCS += netlib_obtainipv6addr.c endif ifeq ($(CONFIG_NETDB_DNSCLIENT),y) -CSRCS += netlib_setipv6dnsaddr.c +CSRCS += netlib_setipv6dnsaddr.c netlib_delipv6dnsaddr.c endif ifeq ($(CONFIG_NET_ROUTE),y) CSRCS += netlib_ipv6route.c netlib_ipv6router.c diff --git a/netutils/netlib/netlib_delipv4dnsaddr.c b/netutils/netlib/netlib_delipv4dnsaddr.c new file mode 100644 index 00000000000..45995d863ab --- /dev/null +++ b/netutils/netlib/netlib_delipv4dnsaddr.c @@ -0,0 +1,97 @@ +/**************************************************************************** + * apps/netutils/netlib/netlib_delipv4dnsaddr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "netutils/netlib.h" + +#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NETDB_DNSCLIENT) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_del_ipv4dnsaddr + * + * Description: + * Remove a DNS server IPv4 address from the list by address + * + * Parameters: + * inaddr The address to remove + * + * Return: + * Zero (OK) is returned on success; A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int netlib_del_ipv4dnsaddr(FAR const struct in_addr *inaddr) +{ + struct sockaddr_in addr; + int ret = -EINVAL; + + if (inaddr) + { + addr.sin_family = AF_INET; + addr.sin_port = 0; + memcpy(&addr.sin_addr, inaddr, sizeof(struct in_addr)); + bzero(&addr.sin_zero, sizeof(addr.sin_zero)); + + ret = dns_del_nameserver((FAR const struct sockaddr *)&addr, + sizeof(struct sockaddr_in)); + } + + return ret; +} + +/**************************************************************************** + * Name: netlib_del_ipv4dnsaddr_by_index + * + * Description: + * Remove a DNS server IPv4 address from the list by index (0-based) + * + * Parameters: + * index: The index of the DNS server to remove (0=first, 1=second, etc.) + * + * Return: + * Zero (OK) is returned on success; A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int netlib_del_ipv4dnsaddr_by_index(int index) +{ + return dns_del_nameserver_by_index(index); +} + +#endif /* CONFIG_NET_IPv4 && CONFIG_NETDB_DNSCLIENT */ diff --git a/netutils/netlib/netlib_delipv6dnsaddr.c b/netutils/netlib/netlib_delipv6dnsaddr.c new file mode 100644 index 00000000000..26abe6028e0 --- /dev/null +++ b/netutils/netlib/netlib_delipv6dnsaddr.c @@ -0,0 +1,97 @@ +/**************************************************************************** + * apps/netutils/netlib/netlib_delipv6dnsaddr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "netutils/netlib.h" + +#if defined(CONFIG_NET_IPv6) && defined(CONFIG_NETDB_DNSCLIENT) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_del_ipv6dnsaddr + * + * Description: + * Remove a DNS server IPv6 address from the list by address + * + * Parameters: + * inaddr The IPv6 address to remove + * + * Return: + * Zero (OK) is returned on success; A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int netlib_del_ipv6dnsaddr(FAR const struct in6_addr *inaddr) +{ + struct sockaddr_in6 addr; + int ret = -EINVAL; + + if (inaddr) + { + /* Del the IPv6 DNS server address */ + + addr.sin6_family = AF_INET6; + addr.sin6_port = 0; + memcpy(&addr.sin6_addr, inaddr, sizeof(struct in6_addr)); + + ret = dns_del_nameserver((FAR const struct sockaddr *)&addr, + sizeof(struct sockaddr_in6)); + } + + return ret; +} + +/**************************************************************************** + * Name: netlib_del_ipv6dnsaddr_by_index + * + * Description: + * Remove a DNS server IPv6 address from the list by index (0-based) + * + * Parameters: + * index:The index of the DNS server to remove (0=first, 1=second, etc.) + * + * Return: + * Zero (OK) is returned on success; A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int netlib_del_ipv6dnsaddr_by_index(int index) +{ + return dns_del_nameserver_by_index(index); +} + +#endif /* CONFIG_NET_IPv6 && CONFIG_NETDB_DNSCLIENT */ diff --git a/netutils/netlib/netlib_obtainipv4addr.c b/netutils/netlib/netlib_obtainipv4addr.c index 6156445f627..5390466fea3 100644 --- a/netutils/netlib/netlib_obtainipv4addr.c +++ b/netutils/netlib/netlib_obtainipv4addr.c @@ -81,13 +81,23 @@ static int dhcp_setup_result(FAR const char *ifname, } #ifdef CONFIG_NETDB_DNSCLIENT - if (ds->dnsaddr.s_addr != 0) + /* Set all received DNS server addresses */ + + if (ds->num_dnsaddr > 0) { - ret = netlib_set_ipv4dnsaddr(&ds->dnsaddr); - if (ret < 0) + uint8_t i; + for (i = 0; i < ds->num_dnsaddr; i++) { - nerr("ERROR: set the DNS server address failed: %d\n", ret); - return ret; + if (ds->dnsaddr[i].s_addr != 0) + { + ret = netlib_set_ipv4dnsaddr(&ds->dnsaddr[i]); + if (ret < 0) + { + nerr("ERROR: set DNS server %d address failed: %d\n", + i, ret); + return ret; + } + } } } #endif