This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 5d15d9741814dd198fa9902bdcb18f5f2b8fb839
Author: zhanghongyu <[email protected]>
AuthorDate: Thu Apr 23 11:50:53 2026 +0800

    netlib: replace DNS ping with gateway ping for connectivity check
    
    Refactor netlib_check_ipconnectivity() to use gateway/router ping instead
    of DNS server ping for network connectivity checks. Add IPv6 support.
    
    Signed-off-by: zhanghongyu <[email protected]>
---
 include/netutils/netlib.h                    |  41 +++-
 netutils/netlib/CMakeLists.txt               |   4 +-
 netutils/netlib/Makefile                     |   4 +-
 netutils/netlib/netlib_checkifconnectivity.c |   7 +-
 netutils/netlib/netlib_checkipconnectivity.c | 341 ++++++++++++++++++++++++---
 5 files changed, 363 insertions(+), 34 deletions(-)

diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h
index eb3933fe9..d76c93e96 100644
--- a/include/netutils/netlib.h
+++ b/include/netutils/netlib.h
@@ -561,12 +561,49 @@ int netlib_getifstatistics(FAR const char *ifname,
 int netlib_check_ifconflict(FAR const char *ifname);
 #endif
 
-#ifdef CONFIG_NETUTILS_PING
+/****************************************************************************
+ * Name: netlib_check_ipconnectivity
+ *
+ * Description:
+ *   Check network connectivity by pinging a remote IP address.
+ *   If ip is NULL, ping the gateway of each network interface,
+ *   and optionally the routers from the routing table. If ping
+ *   is disabled, just check the status of the IP network card.
+ *
+ * Parameters:
+ *   ip       The ipv4 address to check, or NULL to ping gateways
+ *   timeout  The max timeout of each ping
+ *   retry    The retry times of ping
+ *
+ * Return:
+ *   nums of remote reply of ping; a negative or ZERO on failure
+ *
+ ****************************************************************************/
+
 int netlib_check_ipconnectivity(FAR const char *ip, int timeout, int retry);
+
+#ifdef CONFIG_NETUTILS_PING
+
+/****************************************************************************
+ * Name: netlib_check_ifconnectivity
+ *
+ * Description:
+ *   Check network connectivity by pinging the default gateway
+ *   of the specified network interface.
+ *
+ * Parameters:
+ *   ifname   The name of the interface to use
+ *   timeout  The timeout of ping
+ *   retry    The retry times of ping
+ *
+ * Return:
+ *   nums of gateway reply of ping; a negative on failure.
+ *
+ ****************************************************************************/
+
 int netlib_check_ifconnectivity(FAR const char *ifname,
                                 int timeout, int retry);
 #else
-#define netlib_check_ipconnectivity(i, t, r) 1
 #define netlib_check_ifconnectivity(i, t, r) 1
 #endif
 
diff --git a/netutils/netlib/CMakeLists.txt b/netutils/netlib/CMakeLists.txt
index 2f0f11e0f..0a6735121 100644
--- a/netutils/netlib/CMakeLists.txt
+++ b/netutils/netlib/CMakeLists.txt
@@ -158,8 +158,10 @@ if(CONFIG_NETUTILS_NETLIB)
     list(APPEND SRCS netlib_getiobinfo.c)
   endif()
 
+  list(APPEND SRCS netlib_checkipconnectivity.c)
+
   if(CONFIG_NETUTILS_PING)
-    list(APPEND SRCS netlib_checkipconnectivity.c netlib_checkifconnectivity.c)
+    list(APPEND SRCS netlib_checkifconnectivity.c)
   endif()
 
   list(APPEND SRCS netlib_checkhttpconnectivity.c)
diff --git a/netutils/netlib/Makefile b/netutils/netlib/Makefile
index 7bba856b7..5867d9190 100644
--- a/netutils/netlib/Makefile
+++ b/netutils/netlib/Makefile
@@ -157,8 +157,10 @@ ifeq ($(CONFIG_MM_IOB),y)
 CSRCS += netlib_getiobinfo.c
 endif
 
+CSRCS += netlib_checkipconnectivity.c
+
 ifeq ($(CONFIG_NETUTILS_PING),y)
-CSRCS += netlib_checkipconnectivity.c netlib_checkifconnectivity.c
+CSRCS += netlib_checkifconnectivity.c
 endif
 
 CSRCS += netlib_checkhttpconnectivity.c
diff --git a/netutils/netlib/netlib_checkifconnectivity.c 
b/netutils/netlib/netlib_checkifconnectivity.c
index bfc06001a..d0bc8c3e3 100644
--- a/netutils/netlib/netlib_checkifconnectivity.c
+++ b/netutils/netlib/netlib_checkifconnectivity.c
@@ -48,7 +48,8 @@
  * Name: netlib_check_ifconnectivity
  *
  * Description:
- *   Check network interface connectivity by pinging the gateway
+ *   Check network connectivity by pinging the default gateway
+ *   of the specified network interface.
  *
  * Parameters:
  *   ifname   The name of the interface to use
@@ -56,7 +57,7 @@
  *   retry    The retry times of ping
  *
  * Return:
- *   nums of gateway reply of ping; a nagtive on failure.
+ *   nums of gateway reply of ping; a negative on failure.
  *
  ****************************************************************************/
 
@@ -86,4 +87,4 @@ int netlib_check_ifconnectivity(FAR const char *ifname,
   return netlib_check_ipconnectivity(destip, timeout, retry);
 }
 
-#endif /* CONFIG_NETUTILS_PING */
\ No newline at end of file
+#endif /* CONFIG_NETUTILS_PING */
diff --git a/netutils/netlib/netlib_checkipconnectivity.c 
b/netutils/netlib/netlib_checkipconnectivity.c
index 04b3c3c0b..ce1a334b8 100644
--- a/netutils/netlib/netlib_checkipconnectivity.c
+++ b/netutils/netlib/netlib_checkipconnectivity.c
@@ -32,20 +32,22 @@
 #include <string.h>
 #include <errno.h>
 #include <nuttx/debug.h>
+#include <ifaddrs.h>
 
 #include <arpa/inet.h>
 #include <nuttx/net/ip.h>
 
-#include "netutils/icmp_ping.h"
 #include "netutils/netlib.h"
-
-#ifdef CONFIG_NETUTILS_PING
+#include "netutils/icmp_ping.h"
+#include "netutils/icmpv6_ping.h"
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
-#define PING_IPADDR_DATALEN  80
+#define PING_IPADDR_DATALEN  56
+
+#ifdef CONFIG_NETUTILS_PING
 
 /****************************************************************************
  * Private Functions
@@ -72,6 +74,243 @@ static void ping_ipaddr_callback(FAR const struct 
ping_result_s *result)
     }
 }
 
+#endif /* CONFIG_NETUTILS_PING */
+
+#ifdef CONFIG_NETUTILS_PING6
+
+/****************************************************************************
+ * Name: ping6_ipaddr_callback
+ *
+ * Description:
+ *   ping6 ipaddr callback
+ *
+ * Parameters:
+ *   result  The result of ping6
+ *
+ ****************************************************************************/
+
+static void ping6_ipaddr_callback(FAR const struct ping6_result_s *result)
+{
+  FAR int *count = result->info->priv;
+
+  if (result->code == ICMPv6_I_FINISH)
+    {
+      *count = result->nreplies;
+    }
+}
+
+#endif /* CONFIG_NETUTILS_PING6 */
+
+/****************************************************************************
+ * Name: ping_gateway
+ *
+ * Description:
+ *   Ping the default gateway of each network interface (IPv4 and IPv6).
+ *
+ * Parameters:
+ *   info   Pointer to the IPv4 ping info structure
+ *   info6  Pointer to the IPv6 ping info structure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NETDEV_IFINDEX
+static void ping_gateway(FAR struct ping_info_s *info,
+                         FAR struct ping6_info_s *info6)
+{
+  FAR int *replies = info->priv;
+  FAR struct ifaddrs *ifap;
+  FAR struct ifaddrs *ifa;
+
+  if (getifaddrs(&ifap) < 0)
+    {
+      return;
+    }
+
+  for (ifa = ifap; ifa != NULL && *replies == 0; ifa = ifa->ifa_next)
+    {
+      if (ifa->ifa_addr == NULL)
+        {
+          continue;
+        }
+
+      /* Skip interfaces that are not up and running */
+
+      if ((ifa->ifa_flags & (IFF_UP | IFF_RUNNING)) !=
+          (IFF_UP | IFF_RUNNING) || (ifa->ifa_flags & IFF_LOOPBACK) != 0)
+        {
+          continue;
+        }
+
+      if (ifa->ifa_addr->sa_family == AF_INET)
+        {
+          FAR struct sockaddr_in *sin;
+          char destip[INET_ADDRSTRLEN];
+
+          /* Skip interfaces with INADDR_ANY address and loopback flag */
+
+          sin = (FAR struct sockaddr_in *)ifa->ifa_addr;
+          if (sin->sin_addr.s_addr == INADDR_ANY)
+            {
+              continue;
+            }
+
+          /* No ARP means point-to-point or tunnel, treat as reachable */
+
+          if ((ifa->ifa_flags & IFF_NOARP) != 0)
+            {
+              (*replies)++;
+              break;
+            }
+
+          sin = (FAR struct sockaddr_in *)ifa->ifa_dstaddr;
+          if (sin == NULL ||
+              sin->sin_family != AF_INET ||
+              sin->sin_addr.s_addr == INADDR_ANY)
+            {
+              continue;
+            }
+
+          inet_ntop(AF_INET, &sin->sin_addr, destip, sizeof(destip));
+          ninfo("ping gateway %s on %s\n", destip, ifa->ifa_name);
+          info->hostname = destip;
+#ifdef CONFIG_NETUTILS_PING
+          icmp_ping(info);
+#else
+          (*replies)++;
+#endif
+        }
+      else if (ifa->ifa_addr->sa_family == AF_INET6)
+        {
+          FAR struct sockaddr_in6 *sin6;
+          char destip[INET6_ADDRSTRLEN];
+
+          /* Skip interfaces with unspecified address and loopback flag */
+
+          sin6 = (FAR struct sockaddr_in6 *)ifa->ifa_addr;
+          if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
+            {
+              continue;
+            }
+
+          /* No ARP means point-to-point or tunnel, treat as reachable */
+
+          if ((ifa->ifa_flags & IFF_NOARP) != 0)
+            {
+              (*replies)++;
+              break;
+            }
+
+          sin6 = (FAR struct sockaddr_in6 *)ifa->ifa_dstaddr;
+          if (sin6 == NULL ||
+              sin6->sin6_family != AF_INET6 ||
+              IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
+            {
+              continue;
+            }
+
+          inet_ntop(AF_INET6, &sin6->sin6_addr, destip, sizeof(destip));
+          ninfo("ping6 gateway %s on %s\n", destip, ifa->ifa_name);
+          info6->hostname = destip;
+#ifdef CONFIG_NETUTILS_PING6
+          icmp6_ping(info6);
+#else
+          (*replies)++;
+#endif
+        }
+    }
+
+  freeifaddrs(ifap);
+}
+#endif /* CONFIG_NETDEV_IFINDEX */
+
+/****************************************************************************
+ * Name: ping_route
+ *
+ * Description:
+ *   Ping the router addresses from the IPv4 routing table.
+ *
+ * Parameters:
+ *   info  Pointer to the ping info structure
+ *
+ ****************************************************************************/
+
+#if defined(HAVE_ROUTE_PROCFS) && defined(CONFIG_NETUTILS_PING)
+static void ping_route(FAR struct ping_info_s *info)
+{
+  FAR int *replies = info->priv;
+  FAR FILE *stream;
+  struct netlib_ipv4_route_s route;
+
+  stream = netlib_open_ipv4route();
+  if (stream == NULL)
+    {
+      return;
+    }
+
+  while (*replies == 0 && netlib_read_ipv4route(stream, &route) > 0)
+    {
+      char destip[INET_ADDRSTRLEN];
+
+      if (route.router == INADDR_ANY)
+        {
+          continue;
+        }
+
+      inet_ntop(AF_INET, &route.router, destip, sizeof(destip));
+      ninfo("ping route gateway %s\n", destip);
+      info->hostname = destip;
+      icmp_ping(info);
+    }
+
+  netlib_close_ipv4route(stream);
+}
+#endif /* HAVE_ROUTE_PROCFS && CONFIG_NETUTILS_PING */
+
+/****************************************************************************
+ * Name: ping6_route
+ *
+ * Description:
+ *   Ping the router addresses from the IPv6 routing table.
+ *
+ * Parameters:
+ *   info6  Pointer to the ping6 info structure
+ *
+ ****************************************************************************/
+
+#if defined(HAVE_ROUTE_PROCFS) && defined(CONFIG_NETUTILS_PING6)
+static void ping6_route(FAR struct ping6_info_s *info6)
+{
+  FAR int *replies = info6->priv;
+  FAR FILE *stream;
+  struct netlib_ipv6_route_s route;
+
+  stream = netlib_open_ipv6route();
+  if (stream == NULL)
+    {
+      return;
+    }
+
+  while (*replies == 0 && netlib_read_ipv6route(stream, &route) > 0)
+    {
+      char destip[INET6_ADDRSTRLEN];
+      struct in6_addr router;
+
+      memcpy(&router, route.router, sizeof(router));
+      if (IN6_IS_ADDR_UNSPECIFIED(&router))
+        {
+          continue;
+        }
+
+      inet_ntop(AF_INET6, &router, destip, sizeof(destip));
+      ninfo("ping6 route gateway %s\n", destip);
+      info6->hostname = destip;
+      icmp6_ping(info6);
+    }
+
+  netlib_close_ipv6route(stream);
+}
+#endif /* HAVE_ROUTE_PROCFS && CONFIG_NETUTILS_PING6 */
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -80,59 +319,107 @@ static void ping_ipaddr_callback(FAR const struct 
ping_result_s *result)
  * Name: netlib_check_ipconnectivity
  *
  * Description:
- *   Get the network dns status
+ *   Check network connectivity by pinging a remote IP address.
+ *   If ip is NULL, ping the gateway of each network interface,
+ *   and optionally the routers from the routing table. If ping
+ *   is disabled, just check the status of the IP network card.
  *
  * Parameters:
- *   ip       The ipv4 address to check
+ *   ip       The ipv4 address to check, or NULL to ping gateways
  *   timeout  The max timeout of each ping
  *   retry    The retry times of ping
  *
  * Return:
- *   nums of remote reply of ping; a nagtive on failure
+ *   nums of remote reply of ping; a negative or ZERO on failure
  *
  ****************************************************************************/
 
 int netlib_check_ipconnectivity(FAR const char *ip, int timeout, int retry)
 {
   int replies = 0;
-#ifdef CONFIG_NETDB_DNSSERVER_IPv4ADDR
-  char ip_str[INET_ADDRSTRLEN];
-  struct in_addr addr;
-#endif
+#if defined(CONFIG_NETDEV_IFINDEX) || defined(CONFIG_NETUTILS_PING)
   struct ping_info_s info;
+#endif
+#if defined(CONFIG_NETDEV_IFINDEX) || defined(CONFIG_NETUTILS_PING6)
+  struct ping6_info_s info6;
+#endif
 
+#ifdef CONFIG_NETUTILS_PING
   info.count    = retry;
   info.datalen  = PING_IPADDR_DATALEN;
   info.delay    = 0;
   info.timeout  = timeout;
   info.callback = ping_ipaddr_callback;
-  info.priv     = &replies;
-#ifdef CONFIG_NET_BINDTODEVICE
+  info.hostname = ip;
+#  ifdef CONFIG_NET_BINDTODEVICE
   info.devname  = NULL;
+#  endif
+#endif
+#if defined(CONFIG_NETDEV_IFINDEX) || defined(CONFIG_NETUTILS_PING)
+  info.priv     = &replies;
 #endif
 
-  /* if ip is NULL we use default DNS server */
+#ifdef CONFIG_NETUTILS_PING6
+  info6.count    = retry;
+  info6.datalen  = PING_IPADDR_DATALEN;
+  info6.delay    = 0;
+  info6.timeout  = timeout;
+  info6.hostname = ip;
+  info6.callback = ping6_ipaddr_callback;
+#  ifdef CONFIG_NET_BINDTODEVICE
+  info6.devname  = NULL;
+#  endif
+#endif
+#if defined(CONFIG_NETDEV_IFINDEX) || defined(CONFIG_NETUTILS_PING6)
+  info6.priv     = &replies;
+#endif
 
-  if (ip == NULL)
+  if (ip != NULL)
     {
-#ifdef CONFIG_NETDB_DNSSERVER_IPv4ADDR
-      addr.s_addr = HTONL(CONFIG_NETDB_DNSSERVER_IPv4ADDR);
-      inet_ntop(AF_INET, &addr, ip_str, INET_ADDRSTRLEN);
-      info.hostname = ip_str;
+      struct in6_addr addr6;
+
+      ninfo("ping ipaddr test %s\n", ip);
+      if (inet_pton(AF_INET6, ip, &addr6) == 1)
+        {
+#ifdef CONFIG_NETUTILS_PING6
+          icmp6_ping(&info6);
+          return replies;
+#else
+          /* Fallback to network card status check */
+#endif
+        }
+      else
+        {
+#ifdef CONFIG_NETUTILS_PING
+          icmp_ping(&info);
+          return replies;
 #else
-      nerr("ERROR: IP is NULL and no DNS server configured\n");
-      return -EINVAL;
+          /* Fallback to network card status check */
 #endif
+        }
     }
-  else
+
+#ifdef CONFIG_NETDEV_IFINDEX
+  ping_gateway(&info, &info6);
+#endif
+
+#if defined(HAVE_ROUTE_PROCFS) && defined(CONFIG_NETUTILS_PING)
+  if (replies == 0)
     {
-      info.hostname = ip;
+      ping_route(&info);
     }
+#endif
 
-  ninfo("ping ipaddr test %s \n", info.hostname);
-  icmp_ping(&info);
+#if defined(HAVE_ROUTE_PROCFS) && defined(CONFIG_NETUTILS_PING6)
+  if (replies == 0)
+    {
+      ping6_route(&info6);
+    }
+#endif
+
+#if !defined(CONFIG_NETDEV_IFINDEX) && !defined(HAVE_ROUTE_PROCFS)
+  replies = 1;
+#endif
 
   return replies;
 }
-
-#endif /* CONFIG_NETUTILS_PING */
\ No newline at end of file

Reply via email to