iot_defines.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /**
  2. * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. /** @file iot_defines.h
  41. *
  42. * @defgroup iot_defines IoT Defines
  43. * @ingroup iot_sdk_common
  44. * @{
  45. * @brief Common IoT definitions that are needed by IoT modules.
  46. *
  47. * @details This module abstracts common data structures and constants related to IoT.
  48. * These definitions can be used by all the IoT modules.
  49. */
  50. #ifndef IOT_DEFINES_H__
  51. #define IOT_DEFINES_H__
  52. #include <stdint.h>
  53. #include <sdk_config.h>
  54. #include <nrf.h>
  55. #ifdef __cplusplus
  56. extern "C" {
  57. #endif
  58. /**@brief Host to network byte-orders on half word. */
  59. //lint -emacro((572),HTONS) // Suppress warning 572 "Excessive shift value"
  60. #define HTONS(val) ((uint16_t)((((val) & 0xff00) >> 8) | ((((val) & 0x00ff) << 8))))
  61. /**@brief Host to network byte-orders on full word. */
  62. //lint -emacro((572),HTONL) // Suppress warning 572 "Excessive shift value"
  63. #define HTONL(val) ((((uint32_t) (val) & 0xff000000) >> 24) | \
  64. (((uint32_t) (val) & 0x00ff0000) >> 8) | \
  65. (((uint32_t) (val) & 0x0000ff00) << 8) | \
  66. (((uint32_t) (val) & 0x000000ff) << 24))
  67. /**@brief Network to host byte-orders on half word. */
  68. #define NTOHS(val) HTONS(val)
  69. /**@brief Network to host byte-orders on full word. */
  70. #define NTOHL(val) HTONL(val)
  71. #if defined(NRF52) || defined(NRF52_SERIES)
  72. #define EUI_64_ADDR_SIZE 8 /**< Size of EUI-64. */
  73. #define IPV6_ADDR_SIZE 16 /**< Size of IPv6 128-bit address. */
  74. #define IPV6_CONTEXT_IDENTIFIER_NONE 0xFF /**< No context identifier in use. */
  75. #if (BLE_6LOWPAN_LEGACY_MODE == 1)
  76. #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. */
  77. #define IPV6_LL_ADDR_SIZE 8 /**< The link-layer address size used in Neighbor Discovery messages. */
  78. #else
  79. #define IPV6_IID_FLIP_VALUE 0x00 /**< RFC 7668 specifies that no bit is flipped when IID is generated from a Bluetooth Device Address. */
  80. #define IPV6_LL_ADDR_SIZE 6 /**< The link-layer address size used in Neighbor Discovery messages. */
  81. #endif
  82. #define IPV6_IP_HEADER_SIZE 40 /**< IPv6 header size. */
  83. #define ICMP6_HEADER_SIZE 8 /**< ICMP header size. */
  84. #define UDP_HEADER_SIZE 8 /**< UDP header size. */
  85. #define COAP_HEADER_SIZE 4 /**< CoAP header size. */
  86. #define IPV6_DEFAULT_VER_TC 0x60 /**< Default value of version and traffic class fields in IPv6 header. */
  87. #define IPV6_DEFAULT_TC_FL 0x00 /**< Default value of traffic class and flow label fields in IPv6 header. */
  88. #define IPV6_DEFAULT_FL 0x00 /**< Default value of the flow label's two last bytes in IPv6 header. */
  89. #define IPV6_NEXT_HEADER_TCP 6 /**< TCP: protocol number. */
  90. #define IPV6_NEXT_HEADER_UDP 17 /**< UDP: protocol number. */
  91. #define IPV6_NEXT_HEADER_ICMP6 58 /**< ICMPv6: protocol number. */
  92. #define IPV6_NEXT_HEADER_RESERVED 255 /**< Reserved value. */
  93. /**@defgroup icmp6_type ICMPv6 message types.
  94. * @ingroup iot_defines
  95. * @{
  96. */
  97. /**@defgroup icmp6_error_type ICMPv6 error messages.
  98. * @ingroup icmp6_type
  99. * @{
  100. */
  101. #define ICMP6_TYPE_DESTINATION_UNREACHABLE 1 /**< ICMPv6: Destination unreachable error message. */
  102. #define ICMP6_TYPE_PACKET_TOO_LONG 2 /**< ICMPv6: Packet too long error message. */
  103. #define ICMP6_TYPE_TIME_EXCEED 3 /**< ICMPv6: Time-out error message. */
  104. #define ICMP6_TYPE_PARAMETER_PROBLEM 4 /**< ICMPv6: Parameter problem error message. */
  105. /** @} */
  106. #define ICMP6_TYPE_ECHO_REQUEST 128 /**< ICMPv6: Echo request message. */
  107. #define ICMP6_TYPE_ECHO_REPLY 129 /**< ICMPv6: Echo reply message. */
  108. #define ICMP6_TYPE_ROUTER_SOLICITATION 133 /**< ICMPv6: Neighbor discovery, router solicitation message. */
  109. #define ICMP6_TYPE_ROUTER_ADVERTISEMENT 134 /**< ICMPv6: Neighbor discovery, router advertisement message. */
  110. #define ICMP6_TYPE_NEIGHBOR_SOLICITATION 135 /**< ICMPv6: Neighbor discovery, neighbor solicitation message. */
  111. #define ICMP6_TYPE_NEIGHBOR_ADVERTISEMENT 136 /**< ICMPv6: Neighbor discovery, neighbor advertisement message. */
  112. /** @} */
  113. /**@brief Initializes IPv6 address. */
  114. #define IPV6_ADDRESS_INITIALIZE(ADDR) \
  115. memset((ADDR)->u8, 0, IPV6_ADDR_SIZE)
  116. /**@brief Checks if prefixes match. Length in bits. */
  117. #define IPV6_ADDRESS_PREFIX_CMP(prefix, prefix2, length) \
  118. ((0 == memcmp(prefix, prefix2, (length>>3) - ((length & 0x7) ? 1 : 0) )) && \
  119. (((prefix[(length>>3)] & (((0xff00) >> (length & 0x7))))) == \
  120. (prefix2[(length>>3)] & (((0xff00) >> (length & 0x7))))) \
  121. )
  122. /**@brief Sets address prefix. Length in bits. */
  123. #define IPV6_ADDRESS_PREFIX_SET(pfx_to, pfx_from, length) \
  124. do { \
  125. memcpy(pfx_to, pfx_from, length>>3); \
  126. if (length & 0x7) { \
  127. uint8_t mask = ((0xff00) >> (length & 0x7)); \
  128. uint8_t last = pfx_from[length>>3] & mask; \
  129. pfx_to[length>>3] &= ~mask; \
  130. pfx_to[length>>3] |= last; \
  131. } \
  132. } while (0)
  133. /**@brief Creates EUI-64 address from EUI-48.
  134. */
  135. #define IPV6_EUI64_CREATE_FROM_EUI48(eui64, eui48, addr_type) \
  136. eui64[0] = eui48[5]; \
  137. eui64[1] = eui48[4]; \
  138. eui64[2] = eui48[3]; \
  139. eui64[3] = 0xFF; \
  140. eui64[4] = 0xFE; \
  141. eui64[5] = eui48[2]; \
  142. eui64[6] = eui48[1]; \
  143. eui64[7] = eui48[0]; \
  144. if ((addr_type) == BLE_GAP_ADDR_TYPE_PUBLIC) \
  145. { \
  146. eui64[0] &= ~(IPV6_IID_FLIP_VALUE); \
  147. } \
  148. else \
  149. { \
  150. eui64[0] |= IPV6_IID_FLIP_VALUE; \
  151. }
  152. /**@brief Creates link-local address from EUI-64. */
  153. #define IPV6_CREATE_LINK_LOCAL_FROM_EUI64(addr, eui64) \
  154. (addr)->u32[0] = HTONL(0xFE800000); \
  155. (addr)->u32[1] = 0; \
  156. memcpy((addr)->u8 + 8, eui64, EUI_64_ADDR_SIZE); \
  157. (addr)->u8[8] ^= IPV6_IID_FLIP_VALUE;
  158. /**@brief Checks if address is a link-local address. */
  159. #define IPV6_ADDRESS_IS_LINK_LOCAL(addr) \
  160. ((addr)->u16[0] == HTONS(0xfe80))
  161. /**@brief Checks if address is a multicast address. */
  162. #define IPV6_ADDRESS_IS_MULTICAST(addr) \
  163. ((addr)->u8[0] == 0xff)
  164. /**@brief Checks if address is a multicast all-node address. */
  165. #define IPV6_ADDRESS_IS_ALL_NODE(addr) \
  166. (((addr)->u32[0] == HTONL(0xff020000)) && \
  167. ((addr)->u32[1] == 0) && \
  168. ((addr)->u32[2] == 0) && \
  169. ((addr)->u32[3] == HTONL(0x01)))
  170. /**@brief Checks if address is a multicast all-router address. */
  171. #define IPV6_ADDRESS_IS_ALL_ROUTER(addr) \
  172. (((addr)->u32[0] == HTONL(0xff020000)) && \
  173. ((addr)->u32[1] == 0) && \
  174. ((addr)->u32[2] == 0) && \
  175. ((addr)->u32[3] == HTONL(0x02)))
  176. /**@brief Checks if address is a multicast MLDv2 address. */
  177. #define IPV6_ADDRESS_IS_MLDV2_MCAST(addr) \
  178. (((addr)->u32[0] == HTONL(0xff020000)) && \
  179. ((addr)->u32[1] == 0) && \
  180. ((addr)->u32[2] == 0) && \
  181. ((addr)->u32[3] == HTONL(0x16)))
  182. /**@brief Checks if address is a multicast all-node address. */
  183. #define IPV6_ADDRESS_IS_MULTICAST_SOLICITED_NODE(addr) \
  184. (((addr)->u32[0] == HTONL(0xff020000)) && \
  185. ((addr)->u32[1] == 0) && \
  186. ((addr)->u32[2] == HTONL(0x00000001)) && \
  187. ((addr)->u8[12] == 0xFF))
  188. /**@brief Checks if address is an unspecified address. */
  189. #define IPV6_ADDRESS_IS_UNSPECIFIED(addr) \
  190. (((addr)->u32[0] == 0) && \
  191. ((addr)->u32[1] == 0) && \
  192. ((addr)->u32[2] == 0) && \
  193. ((addr)->u32[3] == 0) \
  194. )
  195. /**@brief Compares two IPv6 addresses. */
  196. #define IPV6_ADDRESS_CMP(addr1, addr2) \
  197. memcmp((addr1)->u8, (addr2)->u8, IPV6_ADDR_SIZE)
  198. /**@brief Swaps two IPv6 addresses. */
  199. #define IPV6_ADDRESS_SWAP(addr1, addr2) \
  200. do { \
  201. ipv6_addr_t addr_temp; \
  202. \
  203. addr_temp = *addr1; \
  204. *addr1 = *addr2; \
  205. *addr2 = addr_temp; \
  206. } while (0);
  207. /**@brief Prints an IPV6 address. */
  208. #define IPV6_ADDRESS_LOG(addr) \
  209. NRF_LOG_RAW_INFO("%02x%02x:%02x%02x:",(addr).u8[0],(addr).u8[1],(addr).u8[2],(addr).u8[3]); \
  210. NRF_LOG_RAW_INFO("%02x%02x:%02x%02x:",(addr).u8[4],(addr).u8[5],(addr).u8[6],(addr).u8[7]); \
  211. NRF_LOG_RAW_INFO("%02x%02x:%02x%02x:",(addr).u8[8],(addr).u8[9],(addr).u8[10],(addr).u8[11]); \
  212. NRF_LOG_RAW_INFO("%02x%02x:%02x%02x\r\n",(addr).u8[12],(addr).u8[13],(addr).u8[14],(addr).u8[15]);
  213. /**< EUI 64 data type. */
  214. typedef struct
  215. {
  216. uint8_t identifier[EUI_64_ADDR_SIZE]; /**< 64-bit identifier. */
  217. } eui64_t;
  218. /**< IPv6 address data type. */
  219. typedef union
  220. {
  221. uint8_t u8[16];
  222. uint16_t u16[8];
  223. uint32_t u32[4];
  224. } ipv6_addr_t;
  225. extern ipv6_addr_t ipv6_addr_any;
  226. #define IPV6_ADDR_ANY &ipv6_addr_any /**< IPV6 address represents any address. */
  227. 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. */
  228. #define EUI64_LOCAL_IID &eui64_local_iid /**< EUI-64 IID of the device. */
  229. /** @brief IPv6 address states. */
  230. typedef enum
  231. {
  232. IPV6_ADDR_STATE_UNUSED = 0, /**< IPv6 address is unused. */
  233. IPV6_ADDR_STATE_TENTATIVE, /**< IPv6 tentative address; DUD must be performed. */
  234. IPV6_ADDR_STATE_PREFERRED, /**< IPv6 preferred address; normal. state. */
  235. IPV6_ADDR_STATE_DEPRECATED /**< IPv6 deprecated address. */
  236. } ipv6_addr_state_t;
  237. /**< IPv6 header structure. */
  238. typedef struct
  239. {
  240. uint8_t version_traffic_class; /**< Version and traffic class field. */
  241. uint8_t traffic_class_flowlabel; /**< Traffic class and flow label field. */
  242. uint16_t flowlabel; /**< Flow label, 2nd part of field. */
  243. uint16_t length; /**< Length of IPv6 payload field. */
  244. uint8_t next_header; /**< Next header field. */
  245. uint8_t hoplimit; /**< Hop limit field. */
  246. ipv6_addr_t srcaddr; /**< IPv6 source address field. */
  247. ipv6_addr_t destaddr; /**< IPv6 destination address field. */
  248. } ipv6_header_t;
  249. /**< IPv6 UDP header structure. */
  250. typedef struct
  251. {
  252. uint16_t srcport; /**< Source port. */
  253. uint16_t destport; /**< Destination port. */
  254. uint16_t length; /**< Length of data with UDP header. */
  255. uint16_t checksum; /**< UDP checksum field. */
  256. } udp6_header_t;
  257. /**< IPv6 ICMP header structure. */
  258. typedef struct
  259. {
  260. uint8_t type; /**< Type of ICMP message. See @ref icmp6_type for possible values. */
  261. uint8_t code; /**< Code related to the type field. */
  262. uint16_t checksum; /**< ICMP6 checksum field. */
  263. union /**< Message specific fields if any. */
  264. {
  265. uint32_t mtu; /**< MTU of next hop limit. Used only with Packet Too Big Error Message. */
  266. uint32_t unused; /**< Unused fields for error messages that do not have any auxiliary information. */
  267. uint32_t offset; /**< Offset field used only with Parameter Problem error message. */
  268. struct { /**< Identifier and sequence number information specific associated with echo request and response. */
  269. uint16_t id; /**< Identifier. */
  270. uint16_t sequence; /**< Sequence number. */
  271. } echo;
  272. } sp;
  273. } icmp6_header_t;
  274. #endif // NRF52
  275. #ifdef __cplusplus
  276. }
  277. #endif
  278. #endif //IOT_DEFINES_H__
  279. /**@} */