ICMPv6: Fix so that ICMPv6 can be used with 6LoWPAN.

This commit is contained in:
Gregory Nutt 2017-07-06 12:00:59 -06:00
parent 76587b2c6f
commit a5f361e984
7 changed files with 84 additions and 70 deletions

View file

@ -2,7 +2,7 @@
* include/nuttx/net/icmpv6.h
* Header file for the NuttX ICMPv6 stack.
*
* Copyright (C) 2007-2009, 2012, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012, 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* This logic was leveraged from uIP which also has a BSD-style license:
@ -123,6 +123,13 @@
#define ICMPv6_PRFX_FLAG_L (1 << 7) /* On-link flag */
#define ICMPv6_PRFX_FLAG_A (1 << 6) /* Autonomous address-configuration flag
/* Return with size of an option (in full octects) using the size of a link
* layer address taking into account a header of the two-bytes.
*/
#define ICMPv6_OPT_SIZE(a) (((a) + 2 + 7) & ~7)
#define ICMPv6_OPT_OCTECTS(a) (((a) + 2 + 7) >> 3)
/****************************************************************************
* Public Type Definitions
****************************************************************************/
@ -178,11 +185,12 @@ struct icmpv6_neighbor_solicit_s
uint8_t opttype; /* Option Type: ICMPv6_OPT_SRCLLADDR */
uint8_t optlen; /* Option length: 1 octet */
#ifdef CONFIG_NET_ETHERNET
uint8_t srclladdr[6]; /* Options: Source link layer address */
#endif
};
#define SIZEOF_ICMPV6_NEIGHBOR_SOLICIT_S(n) \
(sizeof(struct icmpv6_neighbor_solicit_s) + ICMPv6_OPT_SIZE(n) - 8)
/* This the message format for the ICMPv6 Neighbor Advertisement message */
struct icmpv6_neighbor_advertise_s
@ -194,12 +202,14 @@ struct icmpv6_neighbor_advertise_s
net_ipv6addr_t tgtaddr; /* Target IPv6 address */
uint8_t opttype; /* Option Type: ICMPv6_OPT_TGTLLADDR */
uint8_t optlen; /* Option length: 1 octet */
#ifdef CONFIG_NET_ETHERNET
uint8_t optlen; /* Option length in octets */
uint8_t tgtlladdr[6]; /* Options: Target link layer address */
#endif
/* Actual size detemined by optlen */
};
#define SIZEOF_ICMPV6_NEIGHBOR_ADVERTISE_S(n) \
(sizeof(struct icmpv6_neighbor_advertise_s) + ICMPv6_OPT_SIZE(n) - 8)
/* This the message format for the ICMPv6 Router Solicitation message */
struct icmpv6_router_solicit_s
@ -210,12 +220,13 @@ struct icmpv6_router_solicit_s
uint8_t flags[4]; /* See ICMPv6_RADV_FLAG_ definitions (must be zero) */
uint8_t opttype; /* Option Type: ICMPv6_OPT_SRCLLADDR */
uint8_t optlen; /* Option length: 1 octet */
#ifdef CONFIG_NET_ETHERNET
uint8_t optlen; /* Option length in octets */
uint8_t srclladdr[6]; /* Options: Source link layer address */
#endif
};
#define SIZEOF_ICMPV6_ROUTER_SOLICIT_S(n) \
(sizeof(struct icmpv6_router_solicit_s) + ICMPv6_OPT_SIZE(n) - 8)
/* This the message format for the ICMPv6 Router Advertisement message:
* Options may include: ICMPv6_OPT_SRCLLADDR, ICMPv6_OPT_MTU, and/or
* ICMPv6_OPT_PREFIX
@ -231,7 +242,7 @@ struct icmpv6_router_advertise_s
uint16_t lifetime; /* Router lifetime */
uint16_t reachable[2]; /* Reachable time */
uint16_t retrans[2]; /* Retransmission timer */
uint8_t options[1]; /* Options begin here */
/* Options begin here */
};
#define ICMPv6_RADV_MINLEN (16)
@ -280,20 +291,20 @@ struct icmpv6_srclladdr_s
{
uint8_t opttype; /* Octet 1: Option Type: ICMPv6_OPT_SRCLLADDR */
uint8_t optlen; /* " " ": Option length: 1 octet */
#ifdef CONFIG_NET_ETHERNET
uint8_t srclladdr[6]; /* " " ": Options: Source link layer address */
#endif
};
#define SIZEOF_ICMPV6_SRCLLADDR_S(n) ICMPv6_OPT_SIZE(n)
struct icmpv6_tgrlladdr_s
{
uint8_t opttype; /* Octet 1: Option Type: ICMPv6_OPT_TGTLLADDR */
uint8_t optlen; /* " " ": Option length: 1 octet */
#ifdef CONFIG_NET_ETHERNET
uint8_t optlen; /* " " ": Option length in octets */
uint8_t tgtlladdr[6]; /* " " ": Options: Target link layer address */
#endif
};
#define SIZEOF_ICMPV6_TGRLLADDR_S(n) ICMPv6_OPT_SIZE(n)
struct icmpv6_prefixinfo_s
{
uint8_t opttype; /* Octet 1: Option Type: ICMPv6_OPT_PREFIX */

View file

@ -2,7 +2,7 @@
* net/icmpv6/icmpv6_advertise.c
* Send an ICMPv6 Neighbor Advertisement
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2015, 2017 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:
@ -96,6 +96,8 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
{
FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF;
FAR struct icmpv6_neighbor_advertise_s *adv;
uint16_t l1size;
uint16_t l3size;
/* Set up the IPv6 header */
@ -105,8 +107,10 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
/* 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);
l1size = NET_LL_HDRLEN(dev);
l3size = SIZEOF_ICMPV6_NEIGHBOR_ADVERTISE_S(l1size);
icmp->len[0] = (l3size >> 8);
icmp->len[1] = (l3size & 0xff);
icmp->proto = IP_PROTO_ICMP6; /* Next header */
icmp->ttl = 255; /* Hop limit */
@ -133,13 +137,13 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
/* Set up the options */
adv->opttype = ICMPv6_OPT_TGTLLADDR; /* Option type */
adv->optlen = 1; /* Option length = 1 octet */
adv->optlen = ICMPv6_OPT_OCTECTS(l1size); /* Option length in octets */
/* Copy our link layer address into the message
* REVISIT: What if the link layer is not Ethernet?
*/
memcpy(adv->tgtlladdr, &dev->d_mac.ether, IFHWADDRLEN);
memcpy(adv->tgtlladdr, &dev->d_mac, l1size);
/* Calculate the checksum over both the ICMP header and payload */
@ -148,7 +152,7 @@ void icmpv6_advertise(FAR struct net_driver_s *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);
dev->d_len = IPv6_HDRLEN + l3size;
#ifdef CONFIG_NET_ETHERNET
/* Add the size of the Ethernet header */

View file

@ -2,7 +2,7 @@
* net/icmpv6/icmpv6_input.c
* Handling incoming ICMPv6 input
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2015, 2017 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:

View file

@ -58,31 +58,6 @@
#ifdef CONFIG_NET_ICMPv6_ROUTER
/****************************************************************************
* Private Types
****************************************************************************/
/* This is the same as struct icmpv6_router_advertise_s, but with the
* source address and prefix options included for simplicity.
*/
struct icmpv6_radvertise_s
{
uint8_t type; /* Message Type: ICMPV6_ROUTER_ADVERTISE */
uint8_t code; /* Further qualifies the ICMP messages */
uint16_t chksum; /* Checksum of ICMP header and data */
uint8_t hoplimit; /* Current hop limit */
uint8_t flags; /* See ICMPv6_RADV_FLAG_* definitions */
uint16_t lifetime; /* Router lifetime */
uint16_t reachable[2]; /* Reachable time */
uint16_t retrans[2]; /* Retransmission timer */
/* Options */
struct icmpv6_srclladdr_s srcaddr;
struct icmpv6_mtu_s mtu;
struct icmpv6_prefixinfo_s prefix;
};
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -91,7 +66,7 @@ struct icmpv6_radvertise_s
#define ICMPv6BUF ((struct icmpv6_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
#define ICMPv6ADVERTISE \
((struct icmpv6_radvertise_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN])
((struct icmpv6_router_advertise_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN])
/****************************************************************************
* Private Data
@ -134,10 +109,12 @@ static const net_ipv6addr_t g_ipv6_prefix =
void icmpv6_radvertise(FAR struct net_driver_s *dev)
{
FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF;
FAR struct icmpv6_radvertise_s *adv;
FAR struct icmpv6_router_advertise_s *adv;
FAR struct icmpv6_srclladdr_s *srcaddr;
FAR struct icmpv6_mtu_s *mtu;
FAR struct icmpv6_prefixinfo_s *prefix;
uint16_t l1size;
uint16_t l3size;
/* Set up the IPv6 header */
@ -147,8 +124,14 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
/* Length excludes the IPv6 header */
icmp->len[0] = (sizeof(struct icmpv6_radvertise_s) >> 8);
icmp->len[1] = (sizeof(struct icmpv6_radvertise_s) & 0xff);
l1size = NET_LL_HDRLEN(dev);
l3size = sizeof(icmpv6_router_advertise_s) +
SIZEOF_ICMPV6_SRCLLADDR_S(l1size) +
sizeof(struct icmpv6_mtu_s) +
sizeof(icmpv6_prefixinfo_s);
icmp->len[0] = (l3size >> 8);
icmp->len[1] = (l3size & 0xff);
icmp->proto = IP_PROTO_ICMP6; /* Next header */
icmp->ttl = 255; /* Hop limit */
@ -173,13 +156,16 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
/* Set up the source address option */
srcaddr = &adv->srcaddr;
srcaddr = (FAR struct icmpv6_srclladdr_s *)
((FAR uint8_t *)adv + sizeof(icmpv6_router_advertise_s));
srcaddr->opttype = ICMPv6_OPT_SRCLLADDR;
srcaddr->optlen = 1;
memcpy(srcaddr->srclladdr, &dev->d_mac.ether.ether_addr_octet, ETHER_ADDR_LEN);
srcaddr->optlen = ICMPv6_OPT_OCTECTS(l1size);
memcpy(srcaddr->srclladdr, &dev->d_mac, l1size);
/* Set up the MTU option */
mtu = (FAR struct icmpv6_mtu_s *)
((FAR uint8_t *)srcaddr + SIZEOF_ICMPV6_SRCLLADDR_S(l1size));
mtu = &adv->mtu;
mtu->opttype = ICMPv6_OPT_MTU;
mtu->optlen = 1;
@ -189,6 +175,8 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
/* Set up the prefix option */
prefix = (FAR struct icmpv6_prefixinfo_s *)
((FAR uint8_t *)mtu + sizeof(icmpv6_mtu_s));
prefix = &adv->prefix;
prefix->opttype = ICMPv6_OPT_MTU;
prefix->optlen = 4;
@ -210,7 +198,7 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
/* Set the size to the size of the IPv6 header and the payload size */
dev->d_len = IPv6_HDRLEN + sizeof(struct icmpv6_radvertise_s);
dev->d_len = IPv6_HDRLEN + sizeof(struct icmpv6_router_advertise_s);
#ifdef CONFIG_NET_ETHERNET
/* Add the size of the Ethernet header */

View file

@ -1,7 +1,7 @@
/****************************************************************************
* net/icmpv6/icmpv6_rsolicit.c
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -92,6 +92,8 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
FAR struct icmpv6_iphdr_s *icmp;
FAR struct icmpv6_router_solicit_s *sol;
FAR struct eth_hdr_s *eth;
uint16_t l1size;
uint16_t l3size;
/* Set up the IPv6 header (most is probably already in place) */
@ -102,8 +104,10 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
/* Length excludes the IPv6 header */
icmp->len[0] = (sizeof(struct icmpv6_router_solicit_s) >> 8);
icmp->len[1] = (sizeof(struct icmpv6_router_solicit_s) & 0xff);
l1size = NET_LL_HDRLEN(dev);
l3size = SIZEOF_ICMPV6_ROUTER_SOLICIT_S(l1size);
icmp->len[0] = (l3size >> 8);
icmp->len[1] = (l3size & 0xff);
icmp->proto = IP_PROTO_ICMP6; /* Next header */
icmp->ttl = 255; /* Hop limit */
@ -130,14 +134,14 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
/* Set up the options */
sol->opttype = ICMPv6_OPT_SRCLLADDR; /* Option type */
sol->optlen = 1; /* Option length = 1 octet */
sol->opttype = ICMPv6_OPT_SRCLLADDR; /* Option type */
sol->optlen = ICMPv6_OPT_OCTECTS(l1size); /* Option length in octets */
/* Copy our link layer address into the message
* REVISIT: What if the link layer is not Ethernet?
*/
memcpy(sol->srclladdr, dev->d_mac.ether.ether_addr_octet, sizeof(net_ipv6addr_t));
memcpy(sol->srclladdr, &dev->d_mac, l1size);
/* Calculate the checksum over both the ICMP header and payload */
@ -146,7 +150,7 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
/* Set the size to the size of the IPv6 header and the payload size */
dev->d_len = IPv6_HDRLEN + sizeof(struct icmpv6_router_solicit_s);
dev->d_len = IPv6_HDRLEN + l3size;
#ifdef CONFIG_NET_ETHERNET
#ifdef CONFIG_NET_MULTILINK
@ -182,6 +186,7 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
/* Add the size of the layer layer header to the total size of the
* outgoing packet.
*/
dev->d_len += netdev_ipv6_hdrlen(dev);
ninfo("Outgoing ICMPv6 Router Solicitation length: %d (%d)\n",
dev->d_len, (icmp->len[0] << 8) | icmp->len[1]);

View file

@ -1,7 +1,7 @@
/****************************************************************************
* net/icmpv6/icmpv6_solicit.c
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -102,7 +102,8 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
{
FAR struct icmpv6_iphdr_s *icmp;
FAR struct icmpv6_neighbor_solicit_s *sol;
FAR struct eth_hdr_s *eth;
uint16_t l1size;
uint16_t l3size;
/* Set up the IPv6 header (most is probably already in place) */
@ -113,8 +114,10 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
/* Length excludes the IPv6 header */
icmp->len[0] = (sizeof(struct icmpv6_neighbor_solicit_s) >> 8);
icmp->len[1] = (sizeof(struct icmpv6_neighbor_solicit_s) & 0xff);
l1size = NET_LL_HDRLEN(dev);
l3size = SIZEOF_ICMPV6_NEIGHBOR_SOLICIT_S(l1size);
icmp->len[0] = (l3size >> 8);
icmp->len[1] = (l3size & 0xff);
icmp->proto = IP_PROTO_ICMP6; /* Next header */
icmp->ttl = 255; /* Hop limit */
@ -145,14 +148,14 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
/* Set up the options */
sol->opttype = ICMPv6_OPT_SRCLLADDR; /* Option type */
sol->optlen = 1; /* Option length = 1 octet */
sol->opttype = ICMPv6_OPT_SRCLLADDR; /* Option type */
sol->optlen = ICMPv6_OPT_OCTECTS(l1size); /* Option length in octets */
/* Copy our link layer address into the message
* REVISIT: What if the link layer is not Ethernet?
*/
memcpy(sol->srclladdr, &dev->d_mac.ether, IFHWADDRLEN);
memcpy(sol->srclladdr, &dev->d_mac, l1size);
/* Calculate the checksum over both the ICMP header and payload */
@ -161,13 +164,15 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
/* Set the size to the size of the IPv6 header and the payload size */
dev->d_len = IPv6_HDRLEN + sizeof(struct icmpv6_neighbor_solicit_s);
dev->d_len = IPv6_HDRLEN + l3size;
#ifdef CONFIG_NET_ETHERNET
#ifdef CONFIG_NET_MULTILINK
if (dev->d_lltype == NET_LL_ETHERNET)
#endif
{
FAR struct eth_hdr_s *eth;
/* Set the destination IPv6 multicast Ethernet address:
*
* For IPv6 multicast addresses, the Ethernet MAC is derived by

View file

@ -67,6 +67,7 @@
/****************************************************************************
* Public Types
****************************************************************************/
/* Describes the link layer address */
struct neighbor_addr_s