summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-01-23 12:49:49 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-01-23 12:49:49 -0600
commita750be83fc6d44839905b0f92d0e66295c96119b (patch)
treed9c0992c52e5484dd9a82b201a38509622863473 /apps
parentbd98b09f49bd0516ebbd705495e8e0a03bc64b25 (diff)
downloadnuttx-a750be83fc6d44839905b0f92d0e66295c96119b.tar.gz
nuttx-a750be83fc6d44839905b0f92d0e66295c96119b.tar.bz2
nuttx-a750be83fc6d44839905b0f92d0e66295c96119b.zip
apps/nshlib: Add the ping6 command to support checking IPv6 networks. NSH logic is complete but still missing some network level support
Diffstat (limited to 'apps')
-rw-r--r--apps/nshlib/README.txt16
-rw-r--r--apps/nshlib/nsh.h6
-rw-r--r--apps/nshlib/nsh_command.c8
-rw-r--r--apps/nshlib/nsh_netcmds.c319
4 files changed, 265 insertions, 84 deletions
diff --git a/apps/nshlib/README.txt b/apps/nshlib/README.txt
index 01f2401bb..970d6e250 100644
--- a/apps/nshlib/README.txt
+++ b/apps/nshlib/README.txt
@@ -776,6 +776,7 @@ o ps
nsh>
o ping [-c <count>] [-i <interval>] <ip-address>
+ ping6 [-c <count>] [-i <interval>] <ip-address>
Test the network communication with a remote peer. Example,
@@ -794,6 +795,8 @@ o ping [-c <count>] [-i <interval>] <ip-address>
10 packets transmitted, 10 received, 0% packet loss, time 10190 ms
nsh>
+ ping6 differs from ping in that it uses IPv6 addressing.
+
o put [-b|-n] [-f <remote-path>] -h <ip-address> <local-path>
Copy the file at <local-address> to the host whose IP address is
@@ -980,6 +983,7 @@ Command Dependencies on Configuration Settings
mv (((!CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_WRITABLE) || !CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_DESCRIPTORS > 0) (see note 4)
nfsmount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET && CONFIG_NFS
ping CONFIG_NET && CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING && !CONFIG_DISABLE_SIGNALS
+ ping6 CONFIG_NET && CONFIG_NET_ICMPv6 && CONFIG_NET_ICMPv6_PING && !CONFIG_DISABLE_SIGNALS
ps --
put CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0 && MTU >= 558 (see note 1,2)
pwd !CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0
@@ -1023,12 +1027,12 @@ also allow it to squeeze into very small memory footprints.
CONFIG_NSH_DISABLE_MKFATFS, CONFIG_NSH_DISABLE_MKFIFO, CONFIG_NSH_DISABLE_MKRD,
CONFIG_NSH_DISABLE_MH, CONFIG_NSH_DISABLE_MOUNT, CONFIG_NSH_DISABLE_MW,
CONFIG_NSH_DISABLE_MV, CONFIG_NSH_DISABLE_NFSMOUNT, CONFIG_NSH_DISABLE_PS,
- CONFIG_NSH_DISABLE_PING, CONFIG_NSH_DISABLE_PUT, CONFIG_NSH_DISABLE_PWD,
- CONFIG_NSH_DISABLE_RM, CONFIG_NSH_DISABLE_RMDIR, CONFIG_NSH_DISABLE_SET,
- CONFIG_NSH_DISABLE_SH, CONFIG_NSH_DISABLE_SLEEP, CONFIG_NSH_DISABLE_TEST,
- CONFIG_NSH_DISABLE_UMOUNT, CONFIG_NSH_DISABLE_UNSET, CONFIG_NSH_DISABLE_URLDECODE,
- CONFIG_NSH_DISABLE_URLENCODE, CONFIG_NSH_DISABLE_USLEEP, CONFIG_NSH_DISABLE_WGET,
- CONFIG_NSH_DISABLE_XD
+ CONFIG_NSH_DISABLE_PING, CONFIG_NSH_DISABLE_PING6, CONFIG_NSH_DISABLE_PUT,
+ CONFIG_NSH_DISABLE_PWD, CONFIG_NSH_DISABLE_RM, CONFIG_NSH_DISABLE_RMDIR,
+ CONFIG_NSH_DISABLE_SET, CONFIG_NSH_DISABLE_SH, CONFIG_NSH_DISABLE_SLEEP,
+ CONFIG_NSH_DISABLE_TEST, CONFIG_NSH_DISABLE_UMOUNT, CONFIG_NSH_DISABLE_UNSET,
+ CONFIG_NSH_DISABLE_URLDECODE, CONFIG_NSH_DISABLE_URLENCODE, CONFIG_NSH_DISABLE_USLEEP,
+ CONFIG_NSH_DISABLE_WGET, CONFIG_NSH_DISABLE_XD
Verbose help output can be suppressed by defining CONFIG_NSH_HELP_TERSE. In that
case, the help command is still available but will be slightly smaller.
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
index 89c8763b2..1bd41f319 100644
--- a/apps/nshlib/nsh.h
+++ b/apps/nshlib/nsh.h
@@ -963,6 +963,12 @@ void nsh_usbtrace(void);
int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# endif
# endif
+# if defined(CONFIG_NET_ICMPv6) && defined(CONFIG_NET_ICMPv6_PING) && \
+ !defined(CONFIG_DISABLE_SIGNALS)
+# ifndef CONFIG_NSH_DISABLE_PING6
+ int cmd_ping6(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# endif
# if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
# ifndef CONFIG_NSH_DISABLE_PUT
int cmd_put(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
diff --git a/apps/nshlib/nsh_command.c b/apps/nshlib/nsh_command.c
index 3950b3379..fa8efa9c5 100644
--- a/apps/nshlib/nsh_command.c
+++ b/apps/nshlib/nsh_command.c
@@ -1,7 +1,7 @@
/****************************************************************************
* apps/nshlib/nsh_command.c
*
- * Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -323,6 +323,12 @@ static const struct cmdmap_s g_cmdmap[] =
# endif
#endif
+#if defined(CONFIG_NET) && defined(CONFIG_NET_ICMPv6) && defined(CONFIG_NET_ICMPv6_PING) && !defined(CONFIG_DISABLE_SIGNALS)
+# ifndef CONFIG_NSH_DISABLE_PING6
+ { "ping6", cmd_ping6, 2, 6, "[-c <count>] [-i <interval>] <ip-address>" },
+# endif
+#endif
+
#ifndef CONFIG_NSH_DISABLE_PS
{ "ps", cmd_ps, 1, 1, NULL },
#endif
diff --git a/apps/nshlib/nsh_netcmds.c b/apps/nshlib/nsh_netcmds.c
index e9315c4b5..8f6422de7 100644
--- a/apps/nshlib/nsh_netcmds.c
+++ b/apps/nshlib/nsh_netcmds.c
@@ -1,7 +1,7 @@
/****************************************************************************
* apps/nshlib/nsh_netcmds.c
*
- * Copyright (C) 2007-2012, 2014 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2012, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -64,6 +64,8 @@
#include <nuttx/net/netdev.h>
#include <nuttx/net/netstats.h>
#include <nuttx/net/ip.h>
+#include <nuttx/net/icmp.h>
+#include <nuttx/net/icmpv6.h>
#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
!defined(CONFIG_DISABLE_SIGNALS)
@@ -96,9 +98,22 @@
#include "nsh_console.h"
/****************************************************************************
- * Definitions
+ * Pre-processor Definitions
****************************************************************************/
+#undef HAVE_PING
+#undef HAVE_PING6
+
+#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
+ !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_NSH_DISABLE_PING)
+# define HAVE_PING
+#endif
+
+#if defined(CONFIG_NET_ICMPv6) && defined(CONFIG_NET_ICMPv6_PING) && \
+ !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_NSH_DISABLE_PING6)
+# define HAVE_PING6
+#endif
+
/* Size of the ECHO data */
#define DEFAULT_PING_DATALEN 56
@@ -132,8 +147,7 @@ struct tftpc_args_s
* Private Data
****************************************************************************/
-#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
- !defined(CONFIG_DISABLE_SIGNALS)
+#if defined(HAVE_PING) || defined(HAVE_PING6)
static uint16_t g_pingid = 0;
#endif
@@ -149,16 +163,108 @@ static uint16_t g_pingid = 0;
* Name: ping_newid
****************************************************************************/
-#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
- !defined(CONFIG_DISABLE_SIGNALS)
-static inline uint16_t ping_newid(void)
+#if defined(HAVE_PING) || defined(HAVE_PING6)
+static uint16_t ping_newid(void)
{
irqstate_t save = irqsave();
uint16_t ret = ++g_pingid;
irqrestore(save);
return ret;
}
-#endif
+#endif /* HAVE_PING || HAVE_PINg */
+
+/****************************************************************************
+ * Name: ping_options
+ ****************************************************************************/
+
+#if defined(HAVE_PING) || defined(HAVE_PING6)
+static int ping_options(FAR struct nsh_vtbl_s *vtbl,
+ int argc, FAR char **argv,
+ FAR int *count, FAR uint32_t *dsec, FAR char **staddr)
+{
+ FAR const char *fmt = g_fmtarginvalid;
+ bool badarg = false;
+ int option;
+ int tmp;
+
+ /* Get the ping options */
+
+ while ((option = getopt(argc, argv, ":c:i:")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'c':
+ tmp = atoi(optarg);
+ if (tmp < 1 || tmp > 10000)
+ {
+ nsh_output(vtbl, g_fmtargrange, argv[0]);
+ badarg = true;
+ }
+ else
+ {
+ *count = tmp;
+ }
+ break;
+
+ case 'i':
+ tmp = atoi(optarg);
+ if (tmp < 1 || tmp >= 4294)
+ {
+ nsh_output(vtbl, g_fmtargrange, argv[0]);
+ badarg = true;
+ }
+ else
+ {
+ *dsec = 10 * tmp;
+ }
+ break;
+
+ case ':':
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ badarg = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
+ badarg = true;
+ break;
+ }
+ }
+
+ /* If a bad argument was encountered, then return without processing the
+ * command
+ */
+
+ if (badarg)
+ {
+ return ERROR;
+ }
+
+ /* There should be exactly on parameter left on the command-line */
+
+ if (optind == argc-1)
+ {
+ *staddr = argv[optind];
+ }
+ else if (optind >= argc)
+ {
+ fmt = g_fmttoomanyargs;
+ goto errout;
+ }
+ else
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+ return OK;
+
+errout:
+ nsh_output(vtbl, fmt, argv[0]);
+ return ERROR;
+}
+#endif /* HAVE_PING || HAVE_PING6 */
/****************************************************************************
* Name: net_statistics
@@ -963,97 +1069,158 @@ int cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
* Name: cmd_ping
****************************************************************************/
-#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
- !defined(CONFIG_DISABLE_SIGNALS)
-#ifndef CONFIG_NSH_DISABLE_PING
+#ifdef HAVE_PING
int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
- FAR const char *fmt = g_fmtarginvalid;
- const char *staddr;
+ FAR char *staddr;
in_addr_t ipaddr;
uint32_t start;
uint32_t next;
uint32_t dsec = 10;
uint32_t maxwait;
uint16_t id;
- bool badarg = false;
int count = 10;
- int option;
int seqno;
int replies = 0;
int elapsed;
+ int ret;
int tmp;
int i;
/* Get the ping options */
- while ((option = getopt(argc, argv, ":c:i:")) != ERROR)
+ ret = ping_options(vtbl, argc, argv, &count, &dsec, &staddr);
+ if (ret < 0)
{
- switch (option)
- {
- case 'c':
- count = atoi(optarg);
- if (count < 1 || count > 10000)
- {
- nsh_output(vtbl, g_fmtargrange, argv[0]);
- badarg = true;
- }
- break;
-
- case 'i':
- tmp = atoi(optarg);
- if (tmp < 1 || tmp >= 4294)
- {
- nsh_output(vtbl, g_fmtargrange, argv[0]);
- badarg = true;
- }
- else
- {
- dsec = 10 * tmp;
- }
- break;
-
- case ':':
- nsh_output(vtbl, g_fmtargrequired, argv[0]);
- badarg = true;
- break;
-
- case '?':
- default:
- nsh_output(vtbl, g_fmtarginvalid, argv[0]);
- badarg = true;
- break;
- }
+ return ERROR;
}
- /* If a bad argument was encountered, then return without processing the
- * command
- */
+ /* Get the IP address in binary form */
- if (badarg)
+ if (dns_gethostip(staddr, &ipaddr) < 0)
{
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
return ERROR;
}
- /* There should be exactly on parameter left on the command-line */
+ /* Get the ID to use */
- if (optind == argc-1)
+ id = ping_newid();
+
+ /* The maximum wait for a response will be the larger of the inter-ping
+ * time and the configured maximum round-trip time.
+ */
+
+ maxwait = MAX(dsec, CONFIG_NSH_MAX_ROUNDTRIP);
+
+ /* Loop for the specified count */
+
+ nsh_output(vtbl, "PING %d.%d.%d.%d %d bytes of data\n",
+ (ipaddr ) & 0xff, (ipaddr >> 8 ) & 0xff,
+ (ipaddr >> 16 ) & 0xff, (ipaddr >> 24 ) & 0xff,
+ DEFAULT_PING_DATALEN);
+
+ start = clock_systimer();
+ for (i = 1; i <= count; i++)
{
- staddr = argv[optind];
- if (dns_gethostip(staddr, &ipaddr) < 0)
+ /* Send the ECHO request and wait for the response */
+
+ next = clock_systimer();
+ seqno = icmp_ping(ipaddr, id, i, DEFAULT_PING_DATALEN, maxwait);
+
+ /* Was any response returned? We can tell if a non-negative sequence
+ * number was returned.
+ */
+
+ if (seqno >= 0 && seqno <= i)
{
- goto errout;
+ /* Get the elapsed time from the time that the request was
+ * sent until the response was received. If we got a response
+ * to an earlier request, then fudge the elapsed time.
+ */
+
+ elapsed = TICK2MSEC(clock_systimer() - next);
+ if (seqno < i)
+ {
+ elapsed += 100 * dsec * (i - seqno);
+ }
+
+ /* Report the receipt of the reply */
+
+ nsh_output(vtbl, "%d bytes from %s: icmp_seq=%d time=%d ms\n",
+ DEFAULT_PING_DATALEN, staddr, seqno, elapsed);
+ replies++;
+ }
+
+ /* Wait for the remainder of the interval. If the last seqno<i,
+ * then this is a bad idea... we will probably lose the response
+ * to the current request!
+ */
+
+ elapsed = TICK2DSEC(clock_systimer() - next);
+ if (elapsed < dsec)
+ {
+ usleep(100000 * (dsec - elapsed));
}
}
- else if (optind >= argc)
+
+ /* Get the total elapsed time */
+
+ elapsed = TICK2MSEC(clock_systimer() - start);
+
+ /* Calculate the percentage of lost packets */
+
+ tmp = (100*(count - replies) + (count >> 1)) / count;
+
+ nsh_output(vtbl, "%d packets transmitted, %d received, %d%% packet loss, time %d ms\n",
+ count, replies, tmp, elapsed);
+ return OK;
+}
+#endif /* HAVE_PING */
+
+/****************************************************************************
+ * Name: cmd_ping6
+ ****************************************************************************/
+
+#ifdef HAVE_PING6
+int cmd_ping6(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ FAR char *staddr;
+ struct in6_addr ipaddr;
+ uint32_t start;
+ uint32_t next;
+ uint32_t dsec = 10;
+ uint32_t maxwait;
+ uint16_t id;
+ int count = 10;
+ int seqno;
+ int replies = 0;
+ int elapsed;
+ int ret;
+ int tmp;
+ int i;
+
+ /* Get the ping options */
+
+ ret = ping_options(vtbl, argc, argv, &count, &dsec, &staddr);
+ if (ret < 0)
{
- fmt = g_fmttoomanyargs;
- goto errout;
+ return ERROR;
}
- else
+
+ /* Get the IP address in binary form
+ * REVISIT: DNS hostname look-up not yet supported
+ */
+
+#if 0
+ ret = dns_gethostip(staddr, &ipaddr);
+#else
+ ret = inet_pton(AF_INET6, staddr, &ipaddr);
+#endif
+ if (ret < 0)
{
- fmt = g_fmtargrequired;
- goto errout;
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
}
/* Get the ID to use */
@@ -1068,10 +1235,13 @@ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
/* Loop for the specified count */
- nsh_output(vtbl, "PING %d.%d.%d.%d %d bytes of data\n",
- (ipaddr ) & 0xff, (ipaddr >> 8 ) & 0xff,
- (ipaddr >> 16 ) & 0xff, (ipaddr >> 24 ) & 0xff,
- DEFAULT_PING_DATALEN);
+ nsh_output(vtbl,
+ "PING6 %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %d bytes of data\n",
+ ntohs(ipaddr.s6_addr16[0]), ntohs(ipaddr.s6_addr16[1]),
+ ntohs(ipaddr.s6_addr16[2]), ntohs(ipaddr.s6_addr16[3]),
+ ntohs(ipaddr.s6_addr16[4]), ntohs(ipaddr.s6_addr16[5]),
+ ntohs(ipaddr.s6_addr16[6]), ntohs(ipaddr.s6_addr16[7]),
+ count);
start = clock_systimer();
for (i = 1; i <= count; i++)
@@ -1079,7 +1249,7 @@ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
/* Send the ECHO request and wait for the response */
next = clock_systimer();
- seqno = icmp_ping(ipaddr, id, i, DEFAULT_PING_DATALEN, maxwait);
+ seqno = icmpv6_ping(ipaddr.s6_addr16, id, i, DEFAULT_PING_DATALEN, maxwait);
/* Was any response returned? We can tell if a non-negative sequence
* number was returned.
@@ -1128,13 +1298,8 @@ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
nsh_output(vtbl, "%d packets transmitted, %d received, %d%% packet loss, time %d ms\n",
count, replies, tmp, elapsed);
return OK;
-
-errout:
- nsh_output(vtbl, fmt, argv[0]);
- return ERROR;
}
-#endif
-#endif /* CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING */
+#endif /* CONFIG_NET_ICMPv6 && CONFIG_NET_ICMPv6_PING */
/****************************************************************************
* Name: cmd_put