Skip to content

Commit 8ed1614

Browse files
ankohuumasc2008
authored andcommitted
system/ping: Fallback to ping6 for gethost error handling.
When ping only receives an IPv6 DNS response, the current command reports "ping_gethostip" and exits even though ping6 can still handle the target. Keep the existing ping and ping6 netutils interfaces unchanged and add a one-way fallback in the ping command. If IPv4 name resolution fails, ping will spawn ping6 with the same arguments and let ping6 report the final result. Signed-off-by: Shunchao Hu <ankohuu@gmail.com>
1 parent 96a0030 commit 8ed1614

1 file changed

Lines changed: 70 additions & 3 deletions

File tree

system/ping/ping.c

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#include <errno.h>
3535
#include <limits.h>
3636
#include <fixedmath.h>
37+
#include <spawn.h>
38+
#include <sys/wait.h>
3739

3840
#include <nuttx/net/ip.h>
3941

@@ -121,8 +123,6 @@ static void ping_result(FAR const struct ping_result_s *result)
121123
switch (result->code)
122124
{
123125
case ICMP_E_HOSTIP:
124-
fprintf(stderr, "ERROR: ping_gethostip(%s) failed\n",
125-
result->info->hostname);
126126
break;
127127

128128
case ICMP_E_MEMORY:
@@ -279,6 +279,60 @@ static void ping_result(FAR const struct ping_result_s *result)
279279
}
280280
}
281281

282+
#if defined(CONFIG_SYSTEM_PING6) && defined(CONFIG_LIBC_EXECFUNCS)
283+
/****************************************************************************
284+
* Name: ping6_fallback
285+
****************************************************************************/
286+
287+
static int ping6_fallback(int argc, FAR char *argv[])
288+
{
289+
FAR char **child_argv;
290+
pid_t pid;
291+
int ret;
292+
int status;
293+
int i;
294+
295+
child_argv = malloc(sizeof(FAR char *) * (argc + 1));
296+
if (child_argv == NULL)
297+
{
298+
fprintf(stderr, "ERROR: Failed to allocate fallback argv\n");
299+
return EXIT_FAILURE;
300+
}
301+
302+
child_argv[0] = CONFIG_SYSTEM_PING6_PROGNAME;
303+
for (i = 1; i < argc; i++)
304+
{
305+
child_argv[i] = argv[i];
306+
}
307+
308+
child_argv[argc] = NULL;
309+
310+
ret = posix_spawnp(&pid, CONFIG_SYSTEM_PING6_PROGNAME, NULL, NULL,
311+
child_argv, NULL);
312+
free(child_argv);
313+
if (ret != 0)
314+
{
315+
fprintf(stderr, "ERROR: posix_spawnp(%s) failed: %d\n",
316+
CONFIG_SYSTEM_PING6_PROGNAME, ret);
317+
return EXIT_FAILURE;
318+
}
319+
320+
ret = waitpid(pid, &status, 0);
321+
if (ret < 0)
322+
{
323+
fprintf(stderr, "ERROR: waitpid() failed: %d\n", errno);
324+
return EXIT_FAILURE;
325+
}
326+
327+
if (WIFEXITED(status))
328+
{
329+
return WEXITSTATUS(status);
330+
}
331+
332+
return EXIT_FAILURE;
333+
}
334+
#endif
335+
282336
/****************************************************************************
283337
* Public Functions
284338
****************************************************************************/
@@ -403,7 +457,20 @@ int main(int argc, FAR char *argv[])
403457

404458
info.hostname = argv[optind];
405459
icmp_ping(&info);
406-
return priv.code < 0 ? EXIT_FAILURE: EXIT_SUCCESS;
460+
461+
#if defined(CONFIG_SYSTEM_PING6) && defined(CONFIG_LIBC_EXECFUNCS)
462+
if (priv.code == ICMP_E_HOSTIP)
463+
{
464+
return ping6_fallback(argc, argv);
465+
}
466+
#endif
467+
468+
if (priv.code == ICMP_E_HOSTIP)
469+
{
470+
fprintf(stderr, "ERROR: ping_gethostip(%s) failed\n", info.hostname);
471+
}
472+
473+
return priv.code < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
407474

408475
errout_with_usage:
409476
optind = 0;

0 commit comments

Comments
 (0)