summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/net/icmpv6/Make.defs2
-rw-r--r--nuttx/net/icmpv6/icmpv6.h21
-rw-r--r--nuttx/net/icmpv6/icmpv6_advertise.c192
-rw-r--r--nuttx/net/icmpv6/icmpv6_input.c95
4 files changed, 222 insertions, 88 deletions
diff --git a/nuttx/net/icmpv6/Make.defs b/nuttx/net/icmpv6/Make.defs
index 0eb0fe1ca..4e788d0eb 100644
--- a/nuttx/net/icmpv6/Make.defs
+++ b/nuttx/net/icmpv6/Make.defs
@@ -37,7 +37,7 @@ ifeq ($(CONFIG_NET_ICMPv6),y)
# ICMPv6 source files
-NET_CSRCS += icmpv6_input.c icmpv6_solicit.c
+NET_CSRCS += icmpv6_input.c icmpv6_solicit.c icmpv6_advertise.c
ifeq ($(CONFIG_NET_ICMPv6_PING),y)
NET_CSRCS += icmpv6_ping.c
diff --git a/nuttx/net/icmpv6/icmpv6.h b/nuttx/net/icmpv6/icmpv6.h
index 67a6be624..554aa5aa0 100644
--- a/nuttx/net/icmpv6/icmpv6.h
+++ b/nuttx/net/icmpv6/icmpv6.h
@@ -253,6 +253,27 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev);
#endif
/****************************************************************************
+ * Name: icmpv6_advertise
+ *
+ * Description:
+ * Send an ICMPv6 Neighbor Advertisement
+ *
+ * Parameters:
+ * dev - The device driver structure containing the outgoing ICMPv6 packet
+ * buffer
+ *
+ * Return:
+ * Zero (OK) on success; A negated errno value on return.
+ *
+ * Assumptions:
+ * The network is locked
+ *
+ ****************************************************************************/
+
+int icmpv6_advertise(FAR struct net_driver_s *dev,
+ const net_ipv6addr_t destipaddr);
+
+/****************************************************************************
* Function: icmpv6_wait_setup
*
* Description:
diff --git a/nuttx/net/icmpv6/icmpv6_advertise.c b/nuttx/net/icmpv6/icmpv6_advertise.c
new file mode 100644
index 000000000..62edf78f3
--- /dev/null
+++ b/nuttx/net/icmpv6/icmpv6_advertise.c
@@ -0,0 +1,192 @@
+/****************************************************************************
+ * net/icmpv6/icmpv6_advertise.c
+ * Send an ICMPv6 Neighbor Advertisement
+ *
+ * Copyright (C) 2015 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Adapted for NuttX from logic in uIP which also has a BSD-like license:
+ *
+ * Original author Adam Dunkels <adam@dunkels.com>
+ * Copyright () 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <debug.h>
+
+#include <nuttx/net/netconfig.h>
+#include <nuttx/net/netstats.h>
+#include <nuttx/net/netdev.h>
+#include <nuttx/net/icmpv6.h>
+
+#include "utils/utils.h"
+#include "icmpv6/icmpv6.h"
+
+#ifdef CONFIG_NET_ICMPv6
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ETHBUF ((struct eth_hdr_s *)&dev->d_buf[0])
+#define ICMPv6BUF ((struct icmpv6_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
+
+#define ICMPv6ADVERTISE \
+ ((struct icmpv6_neighbor_advertise_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN])
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: icmpv6_advertise
+ *
+ * Description:
+ * Send an ICMPv6 Neighbor Advertisement
+ *
+ * Parameters:
+ * dev - The device driver structure containing the outgoing ICMPv6 packet
+ * buffer
+ *
+ * Return:
+ * Zero (OK) on success; A negated errno value on return.
+ *
+ * Assumptions:
+ * The network is locked
+ *
+ ****************************************************************************/
+
+int 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;
+
+ /* Set up the IPv6 header */
+
+ icmp->vtc = 0x60; /* Version/traffic class (MS) */
+ icmp->tcf = 0; /* Traffic class (LS)/Flow label (MS) */
+ icmp->flow = 0; /* Flow label (LS) */
+
+ /* Length excludes the IPv6 header */
+
+ icmp->len[0] = (sizeof(struct icmpv6_neighbor_advertise_s) >> 8);
+ icmp->len[1] = (sizeof(struct icmpv6_neighbor_advertise_s) & 0xff);
+
+ icmp->proto = IP_PROTO_ICMP6; /* Next header */
+ icmp->ttl = 255; /* Hop limit */
+
+ /* Swap source for destination IP address, add our source IP address */
+
+ net_ipv6addr_copy(icmp->destipaddr, destipaddr);
+ net_ipv6addr_copy(icmp->srcipaddr, dev->d_ipv6addr);
+
+ /* Set up the ICMPv6 Neighbor Advertise response */
+
+ adv = ICMPv6ADVERTISE;
+ adv->type = ICMPv6_NEIGHBOR_ADVERTISE; /* Message type */
+ adv->code = 0; /* Message qualifier */
+ adv->flags[0] = ICMPv6_NADV_FLAG_S | ICMPv6_NADV_FLAG_O; /* Solicited+Override flags. */
+ adv->flags[1] = 0;
+ adv->flags[2] = 0;
+ adv->flags[3] = 0;
+
+ /* Copy the target address into the Neighbor Advertisement message */
+
+ net_ipv6addr_copy(adv->tgtaddr, dev->d_ipv6addr);
+
+ /* Set up the options */
+
+ adv->opttype = ICMPv6_OPT_TGTLLADDR; /* Option type */
+ adv->optlen = 1; /* Option length = 1 octet */
+
+ /* Copy our link layer address into the message
+ * REVISIT: What if the link layer is not Ethernet?
+ */
+
+ memcpy(adv->tgtlladdr, &dev->d_mac, IFHWADDRLEN);
+
+ /* Calculate the checksum over both the ICMP header and payload */
+
+ icmp->chksum = 0;
+ icmp->chksum = ~icmpv6_chksum(dev);
+
+ /* Set the size to the size of the IPv6 header and the payload size */
+
+ dev->d_len = IPv6_HDRLEN + sizeof(struct icmpv6_neighbor_advertise_s);
+
+#ifdef CONFIG_NET_ETHERNET
+ /* Add the size of the Ethernet header */
+
+ dev->d_len += ETH_HDRLEN;
+
+ /* Move the source and to the destination addresses in the Ethernet header
+ * and use our MAC as the new source address
+ */
+
+#ifdef CONFIG_NET_MULTILINK
+ if (dev->d_lltype == NET_LL_ETHERNET)
+#endif
+ {
+ FAR struct eth_hdr_s *eth = ETHBUF;
+
+ memcpy(eth->dest, eth->src, ETHER_ADDR_LEN);
+ memcpy(eth->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN);
+
+ /* Set the IPv6 Ethernet type */
+
+ eth->type = HTONS(ETHTYPE_IP6);
+ }
+#endif
+
+ /* No additional neighbor lookup is required on this packet (We are using
+ * a multicast address).
+ */
+
+ IFF_SET_NOARP(dev->d_flags);
+
+ nllvdbg("Outgoing ICMPv6 Neighbor Advertise length: %d (%d)\n",
+ dev->d_len, (icmp->len[0] << 8) | icmp->len[1]);
+
+#ifdef CONFIG_NET_STATISTICS
+ g_netstats.icmpv6.sent++;
+ g_netstats.ipv6.sent++;
+#endif
+ return OK;
+}
+
+#endif /* CONFIG_NET_ICMPv6 */
diff --git a/nuttx/net/icmpv6/icmpv6_input.c b/nuttx/net/icmpv6/icmpv6_input.c
index b834bb9c9..5842e128e 100644
--- a/nuttx/net/icmpv6/icmpv6_input.c
+++ b/nuttx/net/icmpv6/icmpv6_input.c
@@ -48,17 +48,14 @@
#include <string.h>
#include <debug.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-
#include <nuttx/net/netconfig.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/netstats.h>
-#include <nuttx/net/ip.h>
+#include <nuttx/net/icmpv6.h>
#include "devif/devif.h"
-#include "utils/utils.h"
#include "neighbor/neighbor.h"
+#include "utils/utils.h"
#include "icmpv6/icmpv6.h"
#ifdef CONFIG_NET_ICMPv6
@@ -112,6 +109,7 @@ 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++;
@@ -128,7 +126,6 @@ void icmpv6_input(FAR struct net_driver_s *dev)
case ICMPv6_NEIGHBOR_SOLICIT:
{
FAR struct icmpv6_neighbor_solicit_s *sol;
- FAR struct icmpv6_neighbor_advertise_s *adv;
/* Check if we are the target of the solicitation */
@@ -137,93 +134,17 @@ void icmpv6_input(FAR struct net_driver_s *dev)
{
/* Yes.. Send a neighbor advertisement back to where the neighbor
* solicitation came from.
- *
- * Set up the IPv6 header. Most is probably already in place from
- * the Neighbor Solicitation. We could save some time here.
- */
-
- icmp->vtc = 0x60; /* Version/traffic class (MS) */
- icmp->tcf = 0; /* Traffic class (LS)/Flow label (MS) */
- icmp->flow = 0; /* Flow label (LS) */
-
- /* Length excludes the IPv6 header */
-
- icmp->len[0] = (sizeof(struct icmpv6_neighbor_advertise_s) >> 8);
- icmp->len[1] = (sizeof(struct icmpv6_neighbor_advertise_s) & 0xff);
-
- icmp->proto = IP_PROTO_ICMP6; /* Next header */
- icmp->ttl = 255; /* Hop limit */
-
- /* Swap source for destination IP address, add our source IP
- * address
- */
-
- net_ipv6addr_copy(icmp->destipaddr, icmp->srcipaddr);
- net_ipv6addr_copy(icmp->srcipaddr, dev->d_ipv6addr);
-
- /* Set up the ICMPv6 Neighbor Advertise response */
-
- adv = ICMPv6ADVERTISE;
- adv->type = ICMPv6_NEIGHBOR_ADVERTISE; /* Message type */
- adv->code = 0; /* Message qualifier */
- adv->flags[0] = ICMPv6_NADV_FLAG_S | ICMPv6_NADV_FLAG_O; /* Solicited+Override flags. */
- adv->flags[1] = 0;
- adv->flags[2] = 0;
- adv->flags[3] = 0;
-
- /* Copy the target address into the Neighbor Advertisement message */
-
- net_ipv6addr_copy(adv->tgtaddr, dev->d_ipv6addr);
-
- /* Set up the options */
-
- adv->opttype = ICMPv6_OPT_TGTLLADDR; /* Option type */
- adv->optlen = 1; /* Option length = 1 octet */
-
- /* Copy our link layer address into the message
- * REVISIT: What if the link layer is not Ethernet?
*/
- memcpy(adv->tgtlladdr, &dev->d_mac, IFHWADDRLEN);
-
- /* Calculate the checksum over both the ICMP header and payload */
-
- icmp->chksum = 0;
- icmp->chksum = ~icmpv6_chksum(dev);
-
- /* Set the size to the size of the IPv6 header and the payload size */
-
- dev->d_len = IPv6_HDRLEN + sizeof(struct icmpv6_neighbor_advertise_s);
-
-#ifdef CONFIG_NET_ETHERNET
- /* Add the size of the Ethernet header */
-
- dev->d_len += ETH_HDRLEN;
-
- /* Move the source and to the destination addresses in the
- * Ethernet header and use our MAC as the new source address.
- */
-
-#ifdef CONFIG_NET_MULTILINK
- if (dev->d_lltype == NET_LL_ETHERNET)
-#endif
+ ret = icmpv6_advertise(dev, icmp->srcipaddr);
+ if (ret < 0)
{
- FAR struct eth_hdr_s *eth = ETHBUF;
-
- memcpy(eth->dest, eth->src, ETHER_ADDR_LEN);
- memcpy(eth->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN);
-
- /* Set the IPv6 Ethernet type */
-
- eth->type = HTONS(ETHTYPE_IP6);
+ goto icmpv6_drop_packet;
}
-#endif
- /* No additional neighbor lookup is required on this packet
- * (We are using a multicast address).
- */
+ /* All statistics have been updated */
- IFF_SET_NOARP(dev->d_flags);
+ return;
}
else
{