From 14f1554dbbfa640c0f87ffb3b118a816b2f10f5e Mon Sep 17 00:00:00 2001 From: shichunma Date: Tue, 17 Feb 2026 18:20:17 +0800 Subject: [PATCH] netutils/ping: improve ping and ping6 for error handling dns look for both IPv4/v6 when do dns_query, so when do ping, it should try both ipv4 and ipv6 address before return "ping_gethostip" error. Signed-off-by: Jerry Ma --- include/netutils/icmp_ping.h | 47 +------------------ include/netutils/icmp_pub.h | 82 ++++++++++++++++++++++++++++++++++ include/netutils/icmpv6_ping.h | 47 +------------------ include/netutils/ping_pub.h | 52 +++++++++++++++++++++ netutils/ping/icmp_ping.c | 4 +- netutils/ping/icmpv6_ping.c | 10 ++--- system/ping/ping.c | 61 +++++++++++++++---------- system/ping6/ping6.c | 57 +++++++++++++---------- 8 files changed, 213 insertions(+), 147 deletions(-) create mode 100644 include/netutils/icmp_pub.h create mode 100644 include/netutils/ping_pub.h diff --git a/include/netutils/icmp_ping.h b/include/netutils/icmp_ping.h index d9164afc104..42ca9de652a 100644 --- a/include/netutils/icmp_ping.h +++ b/include/netutils/icmp_ping.h @@ -28,6 +28,7 @@ ****************************************************************************/ #include +#include "icmp_pub.h" /**************************************************************************** * Pre-processor Definitions @@ -42,7 +43,6 @@ /* Negative odd number represent error(unrecoverable) */ -#define ICMP_E_HOSTIP -1 /* extra: not used */ #define ICMP_E_MEMORY -3 /* extra: not used */ #define ICMP_E_SOCKET -5 /* extra: error code */ #define ICMP_E_SENDTO -7 /* extra: error code */ @@ -67,53 +67,8 @@ * Public Types ****************************************************************************/ -struct ping_result_s; - -struct ping_info_s -{ - FAR const char *hostname; /* Host name to ping */ -#ifdef CONFIG_NET_BINDTODEVICE - FAR const char *devname; /* Device name to bind */ -#endif - uint16_t count; /* Number of pings requested */ - uint16_t datalen; /* Number of bytes to be sent */ - uint16_t delay; /* Deciseconds to delay between pings */ - uint16_t timeout; /* Deciseconds to wait response before timeout */ - FAR void *priv; /* Private context for callback */ - void (*callback)(FAR const struct ping_result_s *result); -}; - -struct ping_result_s -{ - int code; /* Notice code ICMP_I/E/W_XXX */ - long extra; /* Extra information for code */ - struct in_addr dest; /* Target address to ping */ - uint16_t nrequests; /* Number of ICMP ECHO requests sent */ - uint16_t nreplies; /* Number of matching ICMP ECHO replies received */ - uint16_t outsize; /* Bytes(include ICMP header) to be sent */ - uint16_t id; /* ICMP_ECHO id */ - uint16_t seqno; /* ICMP_ECHO seqno */ - FAR const struct ping_info_s *info; -}; - /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" -{ -#else -#define EXTERN extern -#endif - -void icmp_ping(FAR const struct ping_info_s *info); - -#undef EXTERN -#ifdef __cplusplus -} -#endif - #endif /* __APPS_INCLUDE_NETUTILS_ICMP_PING_H */ diff --git a/include/netutils/icmp_pub.h b/include/netutils/icmp_pub.h new file mode 100644 index 00000000000..8ba8d53d729 --- /dev/null +++ b/include/netutils/icmp_pub.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * apps/include/netutils/icmp_pub.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_NETUTILS_ICMP_PUB_H +#define __APPS_INCLUDE_NETUTILS_ICMP_PUB_H + +#define ICMP_E_HOSTIP -1 /* extra: not used */ + +struct ping_result_s; + +struct ping_info_s +{ + FAR const char *hostname; /* Host name to ping */ +#ifdef CONFIG_NET_BINDTODEVICE + FAR const char *devname; /* Device name to bind */ +#endif + uint16_t flag; /* v4 or v6 */ + uint16_t count; /* Number of pings requested */ + uint16_t datalen; /* Number of bytes to be sent */ + uint16_t delay; /* Deciseconds to delay between pings */ + uint16_t timeout; /* Deciseconds to wait response before timeout */ + FAR void *priv; /* Private context for callback */ + void (*callback)(FAR const struct ping_result_s *result); +}; + +struct ping_result_s +{ + int code; /* Notice code ICMPv6_I/E/W_XXX */ + long extra; /* Extra information for code */ + union + { +#ifdef CONFIG_SYSTEM_PING + struct in_addr v4; /* Target address to ping */ +#endif +#ifdef CONFIG_SYSTEM_PING6 + struct in6_addr v6; /* Target address to ping */ +#endif + } dest; + uint16_t nrequests; /* Number of ICMP ECHO requests sent */ + uint16_t nreplies; /* Number of matching ICMP ECHO replies received */ + uint16_t outsize; /* Bytes(include ICMP header) to be sent */ + uint16_t id; /* ICMPv6_ECHO id */ + uint16_t seqno; /* ICMPv6_ECHO seqno */ + FAR const struct ping_info_s *info; +}; + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +void icmp_ping(FAR const struct ping_info_s *info); +void icmp6_ping(FAR const struct ping_info_s *info); + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __APPS_INCLUDE_NETUTILS_ICMP_PUB_H */ diff --git a/include/netutils/icmpv6_ping.h b/include/netutils/icmpv6_ping.h index 33db0fc6f61..39691370bec 100644 --- a/include/netutils/icmpv6_ping.h +++ b/include/netutils/icmpv6_ping.h @@ -28,6 +28,7 @@ ****************************************************************************/ #include +#include "icmp_pub.h" /**************************************************************************** * Pre-processor Definitions @@ -42,7 +43,6 @@ /* Negative odd number represent error(unrecoverable) */ -#define ICMPv6_E_HOSTIP -1 /* extra: not used */ #define ICMPv6_E_MEMORY -3 /* extra: not used */ #define ICMPv6_E_SOCKET -5 /* extra: error code */ #define ICMPv6_E_SENDTO -7 /* extra: error code */ @@ -66,53 +66,8 @@ * Public Types ****************************************************************************/ -struct ping6_result_s; - -struct ping6_info_s -{ - FAR const char *hostname; /* Host name to ping */ -#ifdef CONFIG_NET_BINDTODEVICE - FAR const char *devname; /* Device name to bind */ -#endif - uint16_t count; /* Number of pings requested */ - uint16_t datalen; /* Number of bytes to be sent */ - uint16_t delay; /* Deciseconds to delay between pings */ - uint16_t timeout; /* Deciseconds to wait response before timeout */ - FAR void *priv; /* Private context for callback */ - void (*callback)(FAR const struct ping6_result_s *result); -}; - -struct ping6_result_s -{ - int code; /* Notice code ICMPv6_I/E/W_XXX */ - long extra; /* Extra information for code */ - struct in6_addr dest; /* Target address to ping */ - uint16_t nrequests; /* Number of ICMP ECHO requests sent */ - uint16_t nreplies; /* Number of matching ICMP ECHO replies received */ - uint16_t outsize; /* Bytes(include ICMP header) to be sent */ - uint16_t id; /* ICMPv6_ECHO id */ - uint16_t seqno; /* ICMPv6_ECHO seqno */ - FAR const struct ping6_info_s *info; -}; - /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" -{ -#else -#define EXTERN extern -#endif - -void icmp6_ping(FAR const struct ping6_info_s *info); - -#undef EXTERN -#ifdef __cplusplus -} -#endif - #endif /* __APPS_INCLUDE_NETUTILS_ICMP_PING_H */ diff --git a/include/netutils/ping_pub.h b/include/netutils/ping_pub.h new file mode 100644 index 00000000000..18fbf8d3f26 --- /dev/null +++ b/include/netutils/ping_pub.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * apps/include/netutils/ping_pub.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_NETUTILS_PING_PUB_H +#define __APPS_INCLUDE_NETUTILS_PING_PUB_H + +struct ping_priv_s +{ + int code; /* Notice code ICMP_I/E/W_XXX */ + long tmin; /* Minimum round trip time */ + long tmax; /* Maximum round trip time */ + long long tsum; /* Sum of all times, for doing average */ + long long tsum2; /* Sum2 is the sum of the squares of sum ,for doing mean deviation */ +}; + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +void ping_result(FAR const struct ping_result_s *result); +void ping6_result(FAR const struct ping_result_s *result); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_NETUTILS_PING_PUB_H */ diff --git a/netutils/ping/icmp_ping.c b/netutils/ping/icmp_ping.c index 88f006b8f58..3f661c22031 100644 --- a/netutils/ping/icmp_ping.c +++ b/netutils/ping/icmp_ping.c @@ -242,7 +242,7 @@ void icmp_ping(FAR const struct ping_info_s *info) result.info = info; result.id = ping_newid(); result.outsize = ICMP_IOBUFFER_SIZE(info->datalen); - if (ping_gethostip(info->hostname, &result.dest) < 0) + if (ping_gethostip(info->hostname, &result.dest.v4) < 0) { icmp_callback(&result, ICMP_E_HOSTIP, 0); return; @@ -300,7 +300,7 @@ void icmp_ping(FAR const struct ping_info_s *info) memset(&priv->destaddr, 0, sizeof(struct sockaddr_in)); priv->destaddr.sin_family = AF_INET; priv->destaddr.sin_port = 0; - priv->destaddr.sin_addr.s_addr = result.dest.s_addr; + priv->destaddr.sin_addr.s_addr = result.dest.v4.s_addr; icmp_callback(&result, ICMP_I_BEGIN, 0); diff --git a/netutils/ping/icmpv6_ping.c b/netutils/ping/icmpv6_ping.c index c62c329d6f2..a29c90b1443 100644 --- a/netutils/ping/icmpv6_ping.c +++ b/netutils/ping/icmpv6_ping.c @@ -149,7 +149,7 @@ static int ping6_gethostip(FAR const char *hostname, * Name: icmp6_callback ****************************************************************************/ -static void icmp6_callback(FAR struct ping6_result_s *result, +static void icmp6_callback(FAR struct ping_result_s *result, int code, long extra) { result->code = code; @@ -165,9 +165,9 @@ static void icmp6_callback(FAR struct ping6_result_s *result, * Name: icmp6_ping ****************************************************************************/ -void icmp6_ping(FAR const struct ping6_info_s *info) +void icmp6_ping(FAR const struct ping_info_s *info) { - struct ping6_result_s result; + struct ping_result_s result; struct sockaddr_in6 destaddr; struct sockaddr_in6 fromaddr; struct icmp6_filter filter; @@ -197,9 +197,9 @@ void icmp6_ping(FAR const struct ping6_info_s *info) result.info = info; result.id = ping6_newid(); result.outsize = ICMPv6_IOBUFFER_SIZE(info->datalen); - if (ping6_gethostip(info->hostname, &result.dest) < 0) + if (ping6_gethostip(info->hostname, &result.dest.v6) < 0) { - icmp6_callback(&result, ICMPv6_E_HOSTIP, 0); + icmp6_callback(&result, ICMP_E_HOSTIP, 0); return; } diff --git a/system/ping/ping.c b/system/ping/ping.c index f294983a105..1a2b6e50d9d 100644 --- a/system/ping/ping.c +++ b/system/ping/ping.c @@ -38,6 +38,7 @@ #include #include "netutils/icmp_ping.h" +#include "netutils/ping_pub.h" /**************************************************************************** * Pre-processor Definitions @@ -52,15 +53,6 @@ * Private Types ****************************************************************************/ -struct ping_priv_s -{ - int code; /* Notice code ICMP_I/E/W_XXX */ - long tmin; /* Minimum round trip time */ - long tmax; /* Maximum round trip time */ - long long tsum; /* Sum of all times, for doing average */ - long long tsum2; /* Sum2 is the sum of the squares of sum ,for doing mean deviation */ -}; - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -109,9 +101,10 @@ static void show_usage(FAR const char *progname, int exitcode) * Name: ping_result ****************************************************************************/ -static void ping_result(FAR const struct ping_result_s *result) +void ping_result(FAR const struct ping_result_s *result) { FAR struct ping_priv_s *priv = result->info->priv; + int warn_now = 1; if (result->code < 0) { @@ -121,8 +114,16 @@ static void ping_result(FAR const struct ping_result_s *result) switch (result->code) { case ICMP_E_HOSTIP: - fprintf(stderr, "ERROR: ping_gethostip(%s) failed\n", - result->info->hostname); +#ifdef CONFIG_SYSTEM_PING6 + warn_now = result->info->flag & (1 << AF_INET6); +#endif + + if (warn_now) + { + fprintf(stderr, "ERROR: ping_gethostip(%s) failed\n", + result->info->hostname); + } + break; case ICMP_E_MEMORY: @@ -135,10 +136,10 @@ static void ping_result(FAR const struct ping_result_s *result) case ICMP_I_BEGIN: printf("PING %u.%u.%u.%u %u bytes of data\n", - ip4_addr1(result->dest.s_addr), - ip4_addr2(result->dest.s_addr), - ip4_addr3(result->dest.s_addr), - ip4_addr4(result->dest.s_addr), + ip4_addr1(result->dest.v4.s_addr), + ip4_addr2(result->dest.v4.s_addr), + ip4_addr3(result->dest.v4.s_addr), + ip4_addr4(result->dest.v4.s_addr), result->info->datalen); break; @@ -158,10 +159,10 @@ static void ping_result(FAR const struct ping_result_s *result) case ICMP_W_TIMEOUT: printf("No response from %u.%u.%u.%u: icmp_seq=%u time=%ld ms\n", - ip4_addr1(result->dest.s_addr), - ip4_addr2(result->dest.s_addr), - ip4_addr3(result->dest.s_addr), - ip4_addr4(result->dest.s_addr), + ip4_addr1(result->dest.v4.s_addr), + ip4_addr2(result->dest.v4.s_addr), + ip4_addr3(result->dest.v4.s_addr), + ip4_addr4(result->dest.v4.s_addr), result->seqno, result->extra); break; @@ -212,10 +213,10 @@ static void ping_result(FAR const struct ping_result_s *result) printf("%u bytes from %u.%u.%u.%u: icmp_seq=%u time=%ld.%ld ms\n", result->info->datalen, - ip4_addr1(result->dest.s_addr), - ip4_addr2(result->dest.s_addr), - ip4_addr3(result->dest.s_addr), - ip4_addr4(result->dest.s_addr), + ip4_addr1(result->dest.v4.s_addr), + ip4_addr2(result->dest.v4.s_addr), + ip4_addr3(result->dest.v4.s_addr), + ip4_addr4(result->dest.v4.s_addr), result->seqno, result->extra / USEC_PER_MSEC, result->extra % USEC_PER_MSEC / MSEC_PER_DSEC); break; @@ -402,7 +403,19 @@ int main(int argc, FAR char *argv[]) } info.hostname = argv[optind]; +#ifdef CONFIG_SYSTEM_PING6 + info.flag = (1 << AF_INET); +#endif icmp_ping(&info); +#ifdef CONFIG_SYSTEM_PING6 + if ((priv.code == ICMP_E_HOSTIP) && + !(info.flag & (1 << AF_INET6))) + { + info.callback = ping6_result; + icmp6_ping(&info); + } + +#endif return priv.code < 0 ? EXIT_FAILURE: EXIT_SUCCESS; errout_with_usage: diff --git a/system/ping6/ping6.c b/system/ping6/ping6.c index 409f3db0eec..5639657fb81 100644 --- a/system/ping6/ping6.c +++ b/system/ping6/ping6.c @@ -38,6 +38,7 @@ #include #include "netutils/icmpv6_ping.h" +#include "netutils/ping_pub.h" /**************************************************************************** * Pre-processor Definitions @@ -52,19 +53,6 @@ * Private Types ****************************************************************************/ -struct ping6_priv_s -{ - int code; /* Notice code ICMP_I/E/W_XXX */ - long tmin; /* Minimum round trip time */ - long tmax; /* Maximum round trip time */ - long long tsum; /* Sum of all times, for doing average */ - long long tsum2; /* Sum2 is the sum of the squares of sum ,for doing mean deviation */ -}; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Name: show_usage ****************************************************************************/ @@ -109,10 +97,11 @@ static void show_usage(FAR const char *progname, int exitcode) * Name: ping_result ****************************************************************************/ -static void ping6_result(FAR const struct ping6_result_s *result) +void ping6_result(FAR const struct ping_result_s *result) { - FAR struct ping6_priv_s *priv = result->info->priv; + FAR struct ping_priv_s *priv = result->info->priv; char strbuffer[INET6_ADDRSTRLEN]; + int warn_now = 1; if (result->code < 0) { @@ -121,9 +110,17 @@ static void ping6_result(FAR const struct ping6_result_s *result) switch (result->code) { - case ICMPv6_E_HOSTIP: - fprintf(stderr, "ERROR: ping6_gethostip(%s) failed\n", - result->info->hostname); + case ICMP_E_HOSTIP: +#ifdef CONFIG_SYSTEM_PING6 + warn_now = result->info->flag & (1 << AF_INET6); +#endif + + if (warn_now) + { + fprintf(stderr, "ERROR: ping6_gethostip(%s) failed\n", + result->info->hostname); + } + break; case ICMPv6_E_MEMORY: @@ -135,7 +132,7 @@ static void ping6_result(FAR const struct ping6_result_s *result) break; case ICMPv6_I_BEGIN: - inet_ntop(AF_INET6, result->dest.s6_addr16, + inet_ntop(AF_INET6, result->dest.v6.s6_addr16, strbuffer, INET6_ADDRSTRLEN); printf("PING6 %s: %u bytes of data\n", strbuffer, result->info->datalen); @@ -156,7 +153,7 @@ static void ping6_result(FAR const struct ping6_result_s *result) break; case ICMPv6_W_TIMEOUT: - inet_ntop(AF_INET6, result->dest.s6_addr16, strbuffer, + inet_ntop(AF_INET6, result->dest.v6.s6_addr16, strbuffer, INET6_ADDRSTRLEN); printf("No response from %s: icmp_seq=%u time=%ld ms\n", strbuffer, result->seqno, result->extra); @@ -207,7 +204,7 @@ static void ping6_result(FAR const struct ping6_result_s *result) priv->tmax = result->extra; } - inet_ntop(AF_INET6, result->dest.s6_addr16, strbuffer, + inet_ntop(AF_INET6, result->dest.v6.s6_addr16, strbuffer, INET6_ADDRSTRLEN); printf("%u bytes from %s icmp_seq=%u time=%ld.%ld ms\n", result->info->datalen, strbuffer, result->seqno, @@ -280,8 +277,8 @@ static void ping6_result(FAR const struct ping6_result_s *result) int main(int argc, FAR char *argv[]) { - struct ping6_info_s info; - struct ping6_priv_s priv; + struct ping_info_s info; + struct ping_priv_s priv; FAR char *endptr; int exitcode; int option; @@ -301,7 +298,6 @@ int main(int argc, FAR char *argv[]) /* Parse command line options */ exitcode = EXIT_FAILURE; - while ((option = getopt(argc, argv, ":c:i:W:s:I:h")) != ERROR) { switch (option) @@ -394,7 +390,20 @@ int main(int argc, FAR char *argv[]) } info.hostname = argv[optind]; +#ifdef CONFIG_SYSTEM_PING + info.flag = (1 << AF_INET6); +#endif icmp6_ping(&info); +#ifdef CONFIG_SYSTEM_PING + if ((priv.code == ICMP_E_HOSTIP) && + !(info.flag & (1 << AF_INET))) + { + info.callback = ping_result; + icmp_ping(&info); + } + +#endif + return priv.code < 0 ? EXIT_FAILURE: EXIT_SUCCESS; errout_with_usage: