summaryrefslogtreecommitdiff
path: root/nuttx/net
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-02-04 16:13:27 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-02-04 16:13:27 -0600
commit03f2ef027f45ab95d4d953539834a5d9ae2aa4cf (patch)
tree524d0156b517ff6582fa07f12292a31ca3d6876f /nuttx/net
parent74e258a6b586a08d8dd1ed2fa6e0ac91f68fff8d (diff)
downloadnuttx-03f2ef027f45ab95d4d953539834a5d9ae2aa4cf.tar.gz
nuttx-03f2ef027f45ab95d4d953539834a5d9ae2aa4cf.tar.bz2
nuttx-03f2ef027f45ab95d4d953539834a5d9ae2aa4cf.zip
ICMPv6 Auto-configuration: If no router reponds to the Router Solicitation, claim the link local address by sending the Neighbor Advertisement and return success
Diffstat (limited to 'nuttx/net')
-rw-r--r--nuttx/net/icmpv6/icmpv6.h6
-rw-r--r--nuttx/net/icmpv6/icmpv6_advertise.c7
-rw-r--r--nuttx/net/icmpv6/icmpv6_autoconfig.c52
-rw-r--r--nuttx/net/icmpv6/icmpv6_input.c9
4 files changed, 48 insertions, 26 deletions
diff --git a/nuttx/net/icmpv6/icmpv6.h b/nuttx/net/icmpv6/icmpv6.h
index 554aa5aa0..53d345fe9 100644
--- a/nuttx/net/icmpv6/icmpv6.h
+++ b/nuttx/net/icmpv6/icmpv6.h
@@ -263,15 +263,15 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev);
* buffer
*
* Return:
- * Zero (OK) on success; A negated errno value on return.
+ * None.
*
* Assumptions:
* The network is locked
*
****************************************************************************/
-int icmpv6_advertise(FAR struct net_driver_s *dev,
- const net_ipv6addr_t destipaddr);
+void icmpv6_advertise(FAR struct net_driver_s *dev,
+ const net_ipv6addr_t destipaddr);
/****************************************************************************
* Function: icmpv6_wait_setup
diff --git a/nuttx/net/icmpv6/icmpv6_advertise.c b/nuttx/net/icmpv6/icmpv6_advertise.c
index 62edf78f3..fea000ae3 100644
--- a/nuttx/net/icmpv6/icmpv6_advertise.c
+++ b/nuttx/net/icmpv6/icmpv6_advertise.c
@@ -83,15 +83,15 @@
* buffer
*
* Return:
- * Zero (OK) on success; A negated errno value on return.
+ * None
*
* Assumptions:
* The network is locked
*
****************************************************************************/
-int icmpv6_advertise(FAR struct net_driver_s *dev,
- const net_ipv6addr_t destipaddr)
+void icmpv6_advertise(FAR struct net_driver_s *dev,
+ const net_ipv6addr_t destipaddr)
{
FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF;
FAR struct icmpv6_neighbor_advertise_s *adv;
@@ -186,7 +186,6 @@ int icmpv6_advertise(FAR struct net_driver_s *dev,
g_netstats.icmpv6.sent++;
g_netstats.ipv6.sent++;
#endif
- return OK;
}
#endif /* CONFIG_NET_ICMPv6 */
diff --git a/nuttx/net/icmpv6/icmpv6_autoconfig.c b/nuttx/net/icmpv6/icmpv6_autoconfig.c
index 2c0a9a9c9..e688cbecb 100644
--- a/nuttx/net/icmpv6/icmpv6_autoconfig.c
+++ b/nuttx/net/icmpv6/icmpv6_autoconfig.c
@@ -78,6 +78,7 @@ struct icmpv6_router_s
FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
sem_t snd_sem; /* Used to wake up the waiting thread */
volatile bool snd_sent; /* True: if request sent */
+ bool snd_advertise; /* True: Send Neighbor Advertisement */
#ifdef CONFIG_NETDEV_MULTINIC
uint8_t snd_ifname[IFNAMSIZ]; /* Interface name */
#endif
@@ -135,7 +136,18 @@ static uint16_t icmpv6_router_interrupt(FAR struct net_driver_s *dev,
/* It looks like we are good to send the data */
/* Copy the packet data into the device packet buffer and send it */
- icmpv6_rsolicit(dev);
+ if (state->snd_advertise)
+ {
+ /* Send the ICMPv6 Neighbor Advertisement message */
+
+ icmpv6_advertise(dev, g_ipv6_allnodes);
+ }
+ else
+ {
+ /* Send the ICMPv6 Router Solicitation message */
+
+ icmpv6_rsolicit(dev);
+ }
/* Make sure no additional Router Solicitation overwrites this one.
* This flag will be cleared in icmpv6_out().
@@ -159,13 +171,14 @@ static uint16_t icmpv6_router_interrupt(FAR struct net_driver_s *dev,
}
/****************************************************************************
- * Name: icmpv6_send_rsolicit
+ * Name: icmpv6_send_message
*
* Description:
* Send an ICMPv6 Router Solicitation to resolve an IPv6 address.
*
* Parameters:
- * dev - The device to use to send the solicitation
+ * dev - The device to use to send the solicitation
+ * advertise - True: Send the Neighbor Advertisement message
*
* Returned Value:
* Zero (OK) is returned on success; On error a negated errno value is
@@ -176,7 +189,7 @@ static uint16_t icmpv6_router_interrupt(FAR struct net_driver_s *dev,
*
****************************************************************************/
-int icmpv6_send_rsolicit(FAR struct net_driver_s *dev)
+static int icmpv6_send_message(FAR struct net_driver_s *dev, bool advertise)
{
struct icmpv6_router_s state;
int ret;
@@ -210,6 +223,7 @@ int icmpv6_send_rsolicit(FAR struct net_driver_s *dev)
/* Arm the callback */
state.snd_sent = false;
+ state.snd_advertise = advertise;
state.snd_cb->flags = ICMPv6_POLL;
state.snd_cb->priv = (FAR void *)&state;
state.snd_cb->event = icmpv6_router_interrupt;
@@ -242,7 +256,7 @@ errout_with_semaphore:
* Name: icmpv6_wait_radvertise
*
* Description:
- * Wait for the receipt of the Router Advertisment matching the Router
+ * Wait for the receipt of the Router Advertisement matching the Router
* Solicitation that we just sent.
*
* Parameters:
@@ -259,9 +273,9 @@ errout_with_semaphore:
*
****************************************************************************/
-int icmpv6_wait_radvertise(FAR struct net_driver_s *dev,
- FAR struct icmpv6_rnotify_s *notify,
- net_lock_t *save)
+static int icmpv6_wait_radvertise(FAR struct net_driver_s *dev,
+ FAR struct icmpv6_rnotify_s *notify,
+ net_lock_t *save)
{
struct timespec delay;
#ifdef CONFIG_NET_NOINTS
@@ -459,7 +473,7 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
/* Send the ICMPv6 Router solicitation message */
- ret = icmpv6_send_rsolicit(dev);
+ ret = icmpv6_send_message(dev, false);
if (ret < 0)
{
ndbg("ERROR: Failed send router solicitation: %d\n", ret);
@@ -490,11 +504,25 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
ndbg("ERROR: Failed to get the router advertisement: %d (retries=%d)\n",
ret, retries);
- /* Take the network down and return the failure */
+ /* Claim the link local address as ours by sending the ICMPv6 Neighbor
+ * Advertisement message.
+ */
+
+ ret = icmpv6_send_message(dev, true);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed send neighbor advertisement: %d\n", ret);
+ netdev_ifdown(dev);
+ net_unlock(save);
+ return ret;
+ }
+
+ /* Leave the network up and return success (even though things did not
+ * work out quite the way we wanted.
+ */
- netdev_ifdown(dev);
net_unlock(save);
- return ret;
+ return OK;
}
/* 5. Router Direction: The router provides direction to the node on how to
diff --git a/nuttx/net/icmpv6/icmpv6_input.c b/nuttx/net/icmpv6/icmpv6_input.c
index 5842e128e..3ed539ce7 100644
--- a/nuttx/net/icmpv6/icmpv6_input.c
+++ b/nuttx/net/icmpv6/icmpv6_input.c
@@ -109,7 +109,6 @@ struct icmpv6_conn_s g_icmpv6_conn;
void icmpv6_input(FAR struct net_driver_s *dev)
{
FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF;
- int ret;
#ifdef CONFIG_NET_STATISTICS
g_netstats.icmpv6.recv++;
@@ -136,13 +135,9 @@ void icmpv6_input(FAR struct net_driver_s *dev)
* solicitation came from.
*/
- ret = icmpv6_advertise(dev, icmp->srcipaddr);
- if (ret < 0)
- {
- goto icmpv6_drop_packet;
- }
+ icmpv6_advertise(dev, icmp->srcipaddr);
- /* All statistics have been updated */
+ /* All statistics have been updated. Nothing to do but exit. */
return;
}