mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 10:58:49 +08:00
ICMPv6: Fix so that ICMPv6 can be used with 6LoWPAN.
This commit is contained in:
parent
76587b2c6f
commit
a5f361e984
7 changed files with 84 additions and 70 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Describes the link layer address */
|
||||
|
||||
struct neighbor_addr_s
|
||||
|
|
Loading…
Reference in a new issue