spider-bot/fw/nrf52/nrf5_sdk/components/iot/common/iot_defines.h

322 lines
21 KiB
C

/**
* Copyright (c) 2014 - 2019, Nordic Semiconductor ASA
*
* 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, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS 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.
*
*/
/** @file iot_defines.h
*
* @defgroup iot_defines IoT Defines
* @ingroup iot_sdk_common
* @{
* @brief Common IoT definitions that are needed by IoT modules.
*
* @details This module abstracts common data structures and constants related to IoT.
* These definitions can be used by all the IoT modules.
*/
#ifndef IOT_DEFINES_H__
#define IOT_DEFINES_H__
#include <stdint.h>
#include <sdk_config.h>
#include <nrf.h>
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Host to network byte-orders on half word. */
//lint -emacro((572),HTONS) // Suppress warning 572 "Excessive shift value"
#define HTONS(val) ((uint16_t)((((val) & 0xff00) >> 8) | ((((val) & 0x00ff) << 8))))
/**@brief Host to network byte-orders on full word. */
//lint -emacro((572),HTONL) // Suppress warning 572 "Excessive shift value"
#define HTONL(val) ((((uint32_t) (val) & 0xff000000) >> 24) | \
(((uint32_t) (val) & 0x00ff0000) >> 8) | \
(((uint32_t) (val) & 0x0000ff00) << 8) | \
(((uint32_t) (val) & 0x000000ff) << 24))
/**@brief Network to host byte-orders on half word. */
#define NTOHS(val) HTONS(val)
/**@brief Network to host byte-orders on full word. */
#define NTOHL(val) HTONL(val)
#if defined(NRF52) || defined(NRF52_SERIES)
#define EUI_64_ADDR_SIZE 8 /**< Size of EUI-64. */
#define IPV6_ADDR_SIZE 16 /**< Size of IPv6 128-bit address. */
#define IPV6_CONTEXT_IDENTIFIER_NONE 0xFF /**< No context identifier in use. */
#if (BLE_6LOWPAN_LEGACY_MODE == 1)
#define IPV6_IID_FLIP_VALUE 0x02 /**< Value XORed with the first byte of EUI-64 to get IID. In some older Linux implementation, this value could be 0x03. */
#define IPV6_LL_ADDR_SIZE 8 /**< The link-layer address size used in Neighbor Discovery messages. */
#else
#define IPV6_IID_FLIP_VALUE 0x00 /**< RFC 7668 specifies that no bit is flipped when IID is generated from a Bluetooth Device Address. */
#define IPV6_LL_ADDR_SIZE 6 /**< The link-layer address size used in Neighbor Discovery messages. */
#endif
#define IPV6_IP_HEADER_SIZE 40 /**< IPv6 header size. */
#define ICMP6_HEADER_SIZE 8 /**< ICMP header size. */
#define UDP_HEADER_SIZE 8 /**< UDP header size. */
#define COAP_HEADER_SIZE 4 /**< CoAP header size. */
#define IPV6_DEFAULT_VER_TC 0x60 /**< Default value of version and traffic class fields in IPv6 header. */
#define IPV6_DEFAULT_TC_FL 0x00 /**< Default value of traffic class and flow label fields in IPv6 header. */
#define IPV6_DEFAULT_FL 0x00 /**< Default value of the flow label's two last bytes in IPv6 header. */
#define IPV6_NEXT_HEADER_TCP 6 /**< TCP: protocol number. */
#define IPV6_NEXT_HEADER_UDP 17 /**< UDP: protocol number. */
#define IPV6_NEXT_HEADER_ICMP6 58 /**< ICMPv6: protocol number. */
#define IPV6_NEXT_HEADER_RESERVED 255 /**< Reserved value. */
/**@defgroup icmp6_type ICMPv6 message types.
* @ingroup iot_defines
* @{
*/
/**@defgroup icmp6_error_type ICMPv6 error messages.
* @ingroup icmp6_type
* @{
*/
#define ICMP6_TYPE_DESTINATION_UNREACHABLE 1 /**< ICMPv6: Destination unreachable error message. */
#define ICMP6_TYPE_PACKET_TOO_LONG 2 /**< ICMPv6: Packet too long error message. */
#define ICMP6_TYPE_TIME_EXCEED 3 /**< ICMPv6: Time-out error message. */
#define ICMP6_TYPE_PARAMETER_PROBLEM 4 /**< ICMPv6: Parameter problem error message. */
/** @} */
#define ICMP6_TYPE_ECHO_REQUEST 128 /**< ICMPv6: Echo request message. */
#define ICMP6_TYPE_ECHO_REPLY 129 /**< ICMPv6: Echo reply message. */
#define ICMP6_TYPE_ROUTER_SOLICITATION 133 /**< ICMPv6: Neighbor discovery, router solicitation message. */
#define ICMP6_TYPE_ROUTER_ADVERTISEMENT 134 /**< ICMPv6: Neighbor discovery, router advertisement message. */
#define ICMP6_TYPE_NEIGHBOR_SOLICITATION 135 /**< ICMPv6: Neighbor discovery, neighbor solicitation message. */
#define ICMP6_TYPE_NEIGHBOR_ADVERTISEMENT 136 /**< ICMPv6: Neighbor discovery, neighbor advertisement message. */
/** @} */
/**@brief Initializes IPv6 address. */
#define IPV6_ADDRESS_INITIALIZE(ADDR) \
memset((ADDR)->u8, 0, IPV6_ADDR_SIZE)
/**@brief Checks if prefixes match. Length in bits. */
#define IPV6_ADDRESS_PREFIX_CMP(prefix, prefix2, length) \
((0 == memcmp(prefix, prefix2, (length>>3) - ((length & 0x7) ? 1 : 0) )) && \
(((prefix[(length>>3)] & (((0xff00) >> (length & 0x7))))) == \
(prefix2[(length>>3)] & (((0xff00) >> (length & 0x7))))) \
)
/**@brief Sets address prefix. Length in bits. */
#define IPV6_ADDRESS_PREFIX_SET(pfx_to, pfx_from, length) \
do { \
memcpy(pfx_to, pfx_from, length>>3); \
if (length & 0x7) { \
uint8_t mask = ((0xff00) >> (length & 0x7)); \
uint8_t last = pfx_from[length>>3] & mask; \
pfx_to[length>>3] &= ~mask; \
pfx_to[length>>3] |= last; \
} \
} while (0)
/**@brief Creates EUI-64 address from EUI-48.
*/
#define IPV6_EUI64_CREATE_FROM_EUI48(eui64, eui48, addr_type) \
eui64[0] = eui48[5]; \
eui64[1] = eui48[4]; \
eui64[2] = eui48[3]; \
eui64[3] = 0xFF; \
eui64[4] = 0xFE; \
eui64[5] = eui48[2]; \
eui64[6] = eui48[1]; \
eui64[7] = eui48[0]; \
if ((addr_type) == BLE_GAP_ADDR_TYPE_PUBLIC) \
{ \
eui64[0] &= ~(IPV6_IID_FLIP_VALUE); \
} \
else \
{ \
eui64[0] |= IPV6_IID_FLIP_VALUE; \
}
/**@brief Creates link-local address from EUI-64. */
#define IPV6_CREATE_LINK_LOCAL_FROM_EUI64(addr, eui64) \
(addr)->u32[0] = HTONL(0xFE800000); \
(addr)->u32[1] = 0; \
memcpy((addr)->u8 + 8, eui64, EUI_64_ADDR_SIZE); \
(addr)->u8[8] ^= IPV6_IID_FLIP_VALUE;
/**@brief Checks if address is a link-local address. */
#define IPV6_ADDRESS_IS_LINK_LOCAL(addr) \
((addr)->u16[0] == HTONS(0xfe80))
/**@brief Checks if address is a multicast address. */
#define IPV6_ADDRESS_IS_MULTICAST(addr) \
((addr)->u8[0] == 0xff)
/**@brief Checks if address is a multicast all-node address. */
#define IPV6_ADDRESS_IS_ALL_NODE(addr) \
(((addr)->u32[0] == HTONL(0xff020000)) && \
((addr)->u32[1] == 0) && \
((addr)->u32[2] == 0) && \
((addr)->u32[3] == HTONL(0x01)))
/**@brief Checks if address is a multicast all-router address. */
#define IPV6_ADDRESS_IS_ALL_ROUTER(addr) \
(((addr)->u32[0] == HTONL(0xff020000)) && \
((addr)->u32[1] == 0) && \
((addr)->u32[2] == 0) && \
((addr)->u32[3] == HTONL(0x02)))
/**@brief Checks if address is a multicast MLDv2 address. */
#define IPV6_ADDRESS_IS_MLDV2_MCAST(addr) \
(((addr)->u32[0] == HTONL(0xff020000)) && \
((addr)->u32[1] == 0) && \
((addr)->u32[2] == 0) && \
((addr)->u32[3] == HTONL(0x16)))
/**@brief Checks if address is a multicast all-node address. */
#define IPV6_ADDRESS_IS_MULTICAST_SOLICITED_NODE(addr) \
(((addr)->u32[0] == HTONL(0xff020000)) && \
((addr)->u32[1] == 0) && \
((addr)->u32[2] == HTONL(0x00000001)) && \
((addr)->u8[12] == 0xFF))
/**@brief Checks if address is an unspecified address. */
#define IPV6_ADDRESS_IS_UNSPECIFIED(addr) \
(((addr)->u32[0] == 0) && \
((addr)->u32[1] == 0) && \
((addr)->u32[2] == 0) && \
((addr)->u32[3] == 0) \
)
/**@brief Compares two IPv6 addresses. */
#define IPV6_ADDRESS_CMP(addr1, addr2) \
memcmp((addr1)->u8, (addr2)->u8, IPV6_ADDR_SIZE)
/**@brief Swaps two IPv6 addresses. */
#define IPV6_ADDRESS_SWAP(addr1, addr2) \
do { \
ipv6_addr_t addr_temp; \
\
addr_temp = *addr1; \
*addr1 = *addr2; \
*addr2 = addr_temp; \
} while (0);
/**@brief Prints an IPV6 address. */
#define IPV6_ADDRESS_LOG(addr) \
NRF_LOG_RAW_INFO("%02x%02x:%02x%02x:",(addr).u8[0],(addr).u8[1],(addr).u8[2],(addr).u8[3]); \
NRF_LOG_RAW_INFO("%02x%02x:%02x%02x:",(addr).u8[4],(addr).u8[5],(addr).u8[6],(addr).u8[7]); \
NRF_LOG_RAW_INFO("%02x%02x:%02x%02x:",(addr).u8[8],(addr).u8[9],(addr).u8[10],(addr).u8[11]); \
NRF_LOG_RAW_INFO("%02x%02x:%02x%02x\r\n",(addr).u8[12],(addr).u8[13],(addr).u8[14],(addr).u8[15]);
/**< EUI 64 data type. */
typedef struct
{
uint8_t identifier[EUI_64_ADDR_SIZE]; /**< 64-bit identifier. */
} eui64_t;
/**< IPv6 address data type. */
typedef union
{
uint8_t u8[16];
uint16_t u16[8];
uint32_t u32[4];
} ipv6_addr_t;
extern ipv6_addr_t ipv6_addr_any;
#define IPV6_ADDR_ANY &ipv6_addr_any /**< IPV6 address represents any address. */
extern eui64_t eui64_local_iid; /**< External variable assumed to be implemented in the application with desired EUI-64 to be used as the IID for SLAAC. */
#define EUI64_LOCAL_IID &eui64_local_iid /**< EUI-64 IID of the device. */
/** @brief IPv6 address states. */
typedef enum
{
IPV6_ADDR_STATE_UNUSED = 0, /**< IPv6 address is unused. */
IPV6_ADDR_STATE_TENTATIVE, /**< IPv6 tentative address; DUD must be performed. */
IPV6_ADDR_STATE_PREFERRED, /**< IPv6 preferred address; normal. state. */
IPV6_ADDR_STATE_DEPRECATED /**< IPv6 deprecated address. */
} ipv6_addr_state_t;
/**< IPv6 header structure. */
typedef struct
{
uint8_t version_traffic_class; /**< Version and traffic class field. */
uint8_t traffic_class_flowlabel; /**< Traffic class and flow label field. */
uint16_t flowlabel; /**< Flow label, 2nd part of field. */
uint16_t length; /**< Length of IPv6 payload field. */
uint8_t next_header; /**< Next header field. */
uint8_t hoplimit; /**< Hop limit field. */
ipv6_addr_t srcaddr; /**< IPv6 source address field. */
ipv6_addr_t destaddr; /**< IPv6 destination address field. */
} ipv6_header_t;
/**< IPv6 UDP header structure. */
typedef struct
{
uint16_t srcport; /**< Source port. */
uint16_t destport; /**< Destination port. */
uint16_t length; /**< Length of data with UDP header. */
uint16_t checksum; /**< UDP checksum field. */
} udp6_header_t;
/**< IPv6 ICMP header structure. */
typedef struct
{
uint8_t type; /**< Type of ICMP message. See @ref icmp6_type for possible values. */
uint8_t code; /**< Code related to the type field. */
uint16_t checksum; /**< ICMP6 checksum field. */
union /**< Message specific fields if any. */
{
uint32_t mtu; /**< MTU of next hop limit. Used only with Packet Too Big Error Message. */
uint32_t unused; /**< Unused fields for error messages that do not have any auxiliary information. */
uint32_t offset; /**< Offset field used only with Parameter Problem error message. */
struct { /**< Identifier and sequence number information specific associated with echo request and response. */
uint16_t id; /**< Identifier. */
uint16_t sequence; /**< Sequence number. */
} echo;
} sp;
} icmp6_header_t;
#endif // NRF52
#ifdef __cplusplus
}
#endif
#endif //IOT_DEFINES_H__
/**@} */