This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 5d3b2d07d61be260b7cbc7dc26d407c591ba4613 Author: meijian <[email protected]> AuthorDate: Fri Mar 14 17:23:30 2025 +0800 ping: add -I for bind device Add -I option to specify the network device to use for sending ICMP echo requests. This allows users to explicitly bind ping to a specific network interface, which is particularly useful in multi-homed systems with multiple network interfaces. Signed-off-by: meijian <[email protected]> --- include/netutils/icmp_ping.h | 4 ++++ include/netutils/icmpv6_ping.h | 4 ++++ netutils/ping/icmp_ping.c | 14 ++++++++++++++ netutils/ping/icmpv6_ping.c | 14 ++++++++++++++ system/ping/ping.c | 17 ++++++++++++++++- system/ping6/ping6.c | 17 ++++++++++++++++- 6 files changed, 68 insertions(+), 2 deletions(-) diff --git a/include/netutils/icmp_ping.h b/include/netutils/icmp_ping.h index eec500de9..3f8d6c29d 100644 --- a/include/netutils/icmp_ping.h +++ b/include/netutils/icmp_ping.h @@ -50,6 +50,7 @@ #define ICMP_E_POLL -11 /* extra: error code */ #define ICMP_E_RECVFROM -13 /* extra: error code */ #define ICMP_E_RECVSMALL -15 /* extra: recv bytes */ +#define ICMP_E_BINDDEV -17 /* extra: error bind */ /* Negative even number represent warning(recoverable) */ @@ -70,6 +71,9 @@ 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 */ diff --git a/include/netutils/icmpv6_ping.h b/include/netutils/icmpv6_ping.h index 3f793f741..33db0fc6f 100644 --- a/include/netutils/icmpv6_ping.h +++ b/include/netutils/icmpv6_ping.h @@ -50,6 +50,7 @@ #define ICMPv6_E_POLL -11 /* extra: error code */ #define ICMPv6_E_RECVFROM -13 /* extra: error code */ #define ICMPv6_E_RECVSMALL -15 /* extra: recv bytes */ +#define ICMPV6_E_BINDDEV -17 /* extra: error bind */ /* Negative even number represent warning(recoverable) */ @@ -70,6 +71,9 @@ 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 */ diff --git a/netutils/ping/icmp_ping.c b/netutils/ping/icmp_ping.c index efbc8a61a..7aa1d3973 100644 --- a/netutils/ping/icmp_ping.c +++ b/netutils/ping/icmp_ping.c @@ -232,6 +232,20 @@ void icmp_ping(FAR const struct ping_info_s *info) return; } +#ifdef CONFIG_NET_BINDTODEVICE + if (info->devname) + { + ret = setsockopt(priv->sockfd, SOL_SOCKET, SO_BINDTODEVICE, + info->devname, strlen(info->devname)); + if (ret < 0) + { + icmp_callback(&result, ICMP_E_BINDDEV, errno); + free(priv); + return; + } + } +#endif + priv->kickoff = clock(); memset(&priv->destaddr, 0, sizeof(struct sockaddr_in)); diff --git a/netutils/ping/icmpv6_ping.c b/netutils/ping/icmpv6_ping.c index 74cd59ee9..e6a93fc98 100644 --- a/netutils/ping/icmpv6_ping.c +++ b/netutils/ping/icmpv6_ping.c @@ -218,6 +218,20 @@ void icmp6_ping(FAR const struct ping6_info_s *info) return; } +#ifdef CONFIG_NET_BINDTODEVICE + if (info->devname) + { + ret = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, + info->devname, strlen(info->devname)); + if (ret < 0) + { + icmp6_callback(&result, ICMPV6_E_BINDDEV, errno); + free(iobuffer); + return; + } + } +#endif + kickoff = clock(); memset(&destaddr, 0, sizeof(struct sockaddr_in6)); diff --git a/system/ping/ping.c b/system/ping/ping.c index 804522112..1abee622a 100644 --- a/system/ping/ping.c +++ b/system/ping/ping.c @@ -100,6 +100,7 @@ static void show_usage(FAR const char *progname, int exitcode) printf(" -s <size> specifies the number of data bytes to be sent. " "Default %u.\n", ICMP_PING_DATALEN); + printf(" -I <interface> is the bind device for traffic\n"); printf(" -h shows this text and exits.\n"); exit(exitcode); } @@ -172,6 +173,12 @@ static void ping_result(FAR const struct ping_result_s *result) fprintf(stderr, "ERROR: short ICMP packet: %ld\n", result->extra); break; +#ifdef CONFIG_NET_BINDTODEVICE + case ICMP_E_BINDDEV: + fprintf(stderr, "ERROR: setsockopt error: %ld\n", result->extra); + break; +#endif + case ICMP_W_IDDIFF: fprintf(stderr, "WARNING: Ignoring ICMP reply with ID %ld. " @@ -300,7 +307,7 @@ int main(int argc, FAR char *argv[]) exitcode = EXIT_FAILURE; - while ((option = getopt(argc, argv, ":c:i:W:s:h")) != ERROR) + while ((option = getopt(argc, argv, ":c:i:W:s:I:h")) != ERROR) { switch (option) { @@ -360,6 +367,14 @@ int main(int argc, FAR char *argv[]) } break; + case 'I': +#ifdef CONFIG_NET_BINDTODEVICE + info.devname = optarg; +#else + fprintf(stderr, "ERROR: Bind to device not supported\n"); +#endif + break; + case 'h': exitcode = EXIT_SUCCESS; goto errout_with_usage; diff --git a/system/ping6/ping6.c b/system/ping6/ping6.c index 5d18637b8..409f3db0e 100644 --- a/system/ping6/ping6.c +++ b/system/ping6/ping6.c @@ -100,6 +100,7 @@ static void show_usage(FAR const char *progname, int exitcode) printf(" -s <size> specifies the number of data bytes to be sent. " " Default %u.\n", ICMPv6_PING6_DATALEN); + printf(" -I <interface> is the bind device for traffic\n"); printf(" -h shows this text and exits.\n"); exit(exitcode); } @@ -176,6 +177,12 @@ static void ping6_result(FAR const struct ping6_result_s *result) result->extra, result->id); break; +#ifdef CONFIG_NET_BINDTODEVICE + case ICMPV6_E_BINDDEV: + fprintf(stderr, "ERROR: setsockopt error: %ld\n", result->extra); + break; +#endif + case ICMPv6_W_SEQNOBIG: fprintf(stderr, "WARNING: Ignoring ICMP reply to sequence %ld. " @@ -295,7 +302,7 @@ int main(int argc, FAR char *argv[]) exitcode = EXIT_FAILURE; - while ((option = getopt(argc, argv, ":c:i:W:s:h")) != ERROR) + while ((option = getopt(argc, argv, ":c:i:W:s:I:h")) != ERROR) { switch (option) { @@ -355,6 +362,14 @@ int main(int argc, FAR char *argv[]) } break; + case 'I': +#ifdef CONFIG_NET_BINDTODEVICE + info.devname = optarg; +#else + fprintf(stderr, "ERROR: Bind to device not supported\n"); +#endif + break; + case 'h': exitcode = EXIT_SUCCESS; goto errout_with_usage;
