ROHC compression/decompression library
ipv6.h
Go to the documentation of this file.
1 /*
2  * Copyright 2015 Didier Barvaux
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /**
20  * @file ipv6.h
21  * @brief The IPv6 header
22  * @author Didier Barvaux <didier@barvaux.org>
23  */
24 
25 #ifndef ROHC_PROTOCOLS_IPV6_H
26 #define ROHC_PROTOCOLS_IPV6_H
27 
28 #include "rohc_utils.h"
29 
30 #include <stdint.h>
31 #include <stddef.h>
32 
33 #ifdef __KERNEL__
34 # include <endian.h>
35 #else
36 # include "config.h" /* for WORDS_BIGENDIAN */
37 #endif
38 
39 
40 /** The format to print an IPv6 address */
41 #define IPV6_ADDR_FORMAT \
42  "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
43 
44 
45 /** The data to print an IPv6 address in (struct ipv6_addr *) format */
46 #define IPV6_ADDR_IN6(x) \
47  IPV6_ADDR_RAW((x)->u8)
48 
49 
50 /** The data to print an IPv6 address in raw format */
51 #define IPV6_ADDR_RAW(x) \
52  (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5], (x)[6], (x)[7], \
53  (x)[8], (x)[9], (x)[10], (x)[11], (x)[12], (x)[13], (x)[14], (x)[15]
54 
55 
56 /** Compare two IPv6 addresses in (struct ipv6_addr *) format */
57 #define IPV6_ADDR_CMP(x, y) \
58  ((x)->u32[0] == (y)->u32[0] && (x)->u32[1] == (y)->u32[1] && \
59  (x)->u32[2] == (y)->u32[2] && (x)->u32[3] == (y)->u32[3])
60 
61 
62 /**
63  * @brief The IPv6 address
64  */
65 struct ipv6_addr
66 {
67  union /* IPv6 address may be accessed by 8, 16 or 32-bit blocks */
68  {
69  uint8_t u8[16]; /**< The 16 8-bit blocks of the IPv6 address */
70  uint16_t u16[8]; /**< The 8 16-bit blocks of the IPv6 address */
71  uint32_t u32[4]; /**< The 4 32-bit blocks of the IPv6 address */
72  } __attribute__((packed));
73 } __attribute__((packed));
74 
75 
76 /* compiler sanity check for C11-compliant compilers and GCC >= 4.6 */
77 #if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
78  (defined(__GNUC__) && defined(__GNUC_MINOR__) && \
79  (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))))
80 _Static_assert(sizeof(struct ipv6_addr) == 16,
81  "IPv6 address should exactly 16-byte long");
82 #endif
83 
84 
85 /**
86  * @brief The IPv6 header
87  */
88 struct ipv6_hdr
89 {
90  union
91  {
92  uint32_t version_tc_flow; /**< The combined version, TC, Flow Label fields */
93 #define IPV6_VERSION_MASK 0xf0000000U /**< The mask for the Traffic Class (TC) field */
94 #define IPV6_TC_MASK 0x0ff00000U /**< The mask for the Traffic Class (TC) field */
95 #define IPV6_FLOW_MASK 0x000fffffU /**< The mask for the Flow Label field */
96  struct
97  {
98 #if WORDS_BIGENDIAN == 1
99  uint8_t version:4; /**< The IP version */
100  uint8_t tc1:4; /**< The Traffic Class (TC) (part 1) */
101  uint8_t tc2:4; /**< The Traffic Class (TC) (part 2) */
102  uint8_t flowl1:4; /**< The Flow Label (part 1) */
103 #else
104  uint8_t tc1:4;
105  uint8_t version:4;
106  uint8_t flow1:4;
107  uint8_t tc2:4;
108 #endif
109  uint16_t flow2; /**< The Flow Label (part 2) */
110  } __attribute__((packed));
111  struct
112  {
113 #if WORDS_BIGENDIAN == 1
114  uint8_t version_:4; /**< The IP version */
115  uint8_t dscp1:4; /**< The Differentiated Services Code Point (DSCP) (part 1) */
116  uint8_t dscp2:2; /**< The Differentiated Services Code Point (DSCP) (part 2) */
117  uint8_t ecn:2; /**< The Explicit Congestion Notification (ECN) */
118  uint8_t flowl1_:4; /**< The Flow Label (part 1) */
119 #else
120  uint8_t dscp1:4;
121  uint8_t version_:4;
122  uint8_t flowl1_:4;
123  uint8_t ecn:2;
124  uint8_t dscp2:2;
125 #endif
126  uint16_t flow2_; /**< The Flow Label (part 2) */
127  } __attribute__((packed));
128 
129  } __attribute__((packed));
130 
131  uint16_t plen; /**< The Payload Length */
132  uint8_t nh; /**< The protocol of the Next Header (NH) */
133  uint8_t hl; /**< The Hop Limit (HL) */
134  struct ipv6_addr saddr; /**< The source IP address */
135  struct ipv6_addr daddr; /**< The destination IP address */
136 
137 } __attribute__((packed));
138 
139 
140 /* compiler sanity check for C11-compliant compilers and GCC >= 4.6 */
141 #if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
142  (defined(__GNUC__) && defined(__GNUC_MINOR__) && \
143  (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))))
144 _Static_assert(sizeof(struct ipv6_hdr) == 40,
145  "IPv6 header should exactly 40-byte long");
146 #endif
147 
148 
149 /** The maximum value of the length field of one IPv6 extension header */
150 #define IPV6_OPT_HDR_LEN_FIELD_MAX_VAL 0xffU
151 /** The maximum length of one IPv6 extension header */
152 #define IPV6_OPT_HDR_LEN_MAX ((IPV6_OPT_HDR_LEN_FIELD_MAX_VAL + 1) * 8)
153 /** The maximum length for the IPv6 extension header context */
154 #define IPV6_OPT_CTXT_LEN_MAX (IPV6_OPT_HDR_LEN_MAX - 2)
155 
156 
157 /** The IPv6 option header */
158 struct ipv6_opt
159 {
160  uint8_t next_header; /**< The protocol of the next header */
161  uint8_t length; /**< The length of the header in 8-byte units minus 1 */
162  uint8_t value[1]; /**< The start of the IPv6 option header */ /* TODO */
163 } __attribute__((packed));
164 
165 
166 /* compiler sanity check for C11-compliant compilers and GCC >= 4.6 */
167 #if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
168  (defined(__GNUC__) && defined(__GNUC_MINOR__) && \
169  (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))))
170 _Static_assert(sizeof(struct ipv6_opt) == 3,
171  "IPv6 option header should exactly 3-byte long");
172 #endif
173 
174 
175 static inline uint8_t ipv6_get_tc(const struct ipv6_hdr *const ipv6)
176  __attribute__((warn_unused_result, nonnull(1), pure));
177 static inline void ipv6_set_tc(struct ipv6_hdr *const ipv6, const uint8_t tc)
178  __attribute__((nonnull(1)));
179 
180 static inline void ipv6_set_dscp_ecn(struct ipv6_hdr *const ipv6,
181  const uint8_t dscp,
182  const uint8_t ecn)
183  __attribute__((nonnull(1)));
184 
185 static inline uint8_t ipv6_get_dscp(const struct ipv6_hdr *const ipv6)
186  __attribute__((warn_unused_result, nonnull(1), pure));
187 static inline void ipv6_set_dscp(struct ipv6_hdr *const ipv6, const uint8_t dscp)
188  __attribute__((nonnull(1)));
189 
190 static inline uint32_t ipv6_get_flow_label(const struct ipv6_hdr *const ipv6)
191  __attribute__((warn_unused_result, nonnull(1), pure));
192 static inline void ipv6_set_flow_label(struct ipv6_hdr *const ipv6,
193  const uint32_t flow_label)
194  __attribute__((nonnull(1)));
195 
196 static inline size_t ipv6_opt_get_length(const struct ipv6_opt *const opt)
197  __attribute__((warn_unused_result, nonnull(1), pure));
198 
199 
200 /**
201  * @brief Get the Traffic Class (TC) of the given IPv6 packet
202  *
203  * @param ipv6 The header of the IPv6 packet
204  * @return The 8-bit Traffic Class (TC)
205  */
206 static inline uint8_t ipv6_get_tc(const struct ipv6_hdr *const ipv6)
207 {
208  return ((ipv6->tc1 << 4) | ipv6->tc2);
209 }
210 
211 
212 /**
213  * @brief Set the Traffic Class (TC) of the given IPv6 packet
214  *
215  * @param[in,out] ipv6 The header of the IPv6 packet
216  * @param tc The 8-bit Traffic Class (TC)
217  */
218 static inline void ipv6_set_tc(struct ipv6_hdr *const ipv6, const uint8_t tc)
219 {
220  ipv6->tc1 = (tc >> 4) & 0x0f;
221  ipv6->tc2 = tc & 0x0f;
222 }
223 
224 
225 /**
226  * @brief Set the DSCP and ECN of the given IPv6 packet
227  *
228  * @param[in,out] ipv6 The header of the IPv6 packet
229  * @param dscp The 6-bit DSCP
230  * @param ecn The 2-bit ECN
231  */
232 static inline void ipv6_set_dscp_ecn(struct ipv6_hdr *const ipv6,
233  const uint8_t dscp,
234  const uint8_t ecn)
235 {
236  ipv6_set_tc(ipv6, ((dscp << 2) & 0xfc) | (ecn & 0x03));
237 }
238 
239 
240 /**
241  * @brief Get the Differentiated Services Code Point (DSCP) of the given IPv6 packet
242  *
243  * @param ipv6 The header of the IPv6 packet
244  * @return The 6-bit DSCP
245  */
246 static inline uint8_t ipv6_get_dscp(const struct ipv6_hdr *const ipv6)
247 {
248  return ((ipv6->dscp1 << 2) | ipv6->dscp2);
249 }
250 
251 
252 /**
253  * @brief Set the Differentiated Services Code Point (DSCP) of the given IPv6 packet
254  *
255  * @param[in,out] ipv6 The header of the IPv6 packet
256  * @param dscp The 6-bit DSCP
257  */
258 static inline void ipv6_set_dscp(struct ipv6_hdr *const ipv6, const uint8_t dscp)
259 {
260  ipv6->dscp1 = (dscp >> 2) & 0x0f;
261  ipv6->dscp2 = dscp & 0x03;
262 }
263 
264 
265 /**
266  * @brief Get the Flow Label of the given IPv6 packet
267  *
268  * @param ipv6 The header of the IPv6 packet
269  * @return The 20-bit Flow Label
270  */
271 static inline uint32_t ipv6_get_flow_label(const struct ipv6_hdr *const ipv6)
272 {
273  return (rohc_ntoh32(ipv6->version_tc_flow) & IPV6_FLOW_MASK);
274 }
275 
276 
277 /**
278  * @brief Set the Flow Label of the given IPv6 packet
279  *
280  * @param[in,out] ipv6 The header of the IPv6 packet
281  * @param flow_label The 20-bit Flow Label
282  */
283 static inline void ipv6_set_flow_label(struct ipv6_hdr *const ipv6,
284  const uint32_t flow_label)
285 {
286  ipv6->flow1 = (flow_label >> 16);
287  ipv6->flow2 = rohc_hton16(flow_label & 0xffff);
288 }
289 
290 
291 /**
292  * @brief get the length (in bytes) of the IPv6 option header
293  *
294  * @param opt The IPv6 option header
295  * @return The length (in bytes) of the IPv6 option header
296  */
297 static inline size_t ipv6_opt_get_length(const struct ipv6_opt *const opt)
298 {
299  return ((opt->length + 1) * 8);
300 }
301 
302 
303 #endif
304 
uint16_t flow2_
Definition: ipv6.h:126
static uint32_t ipv6_get_flow_label(const struct ipv6_hdr *const ipv6)
Get the Flow Label of the given IPv6 packet.
Definition: ipv6.h:271
uint8_t next_header
Definition: ipv6.h:160
uint16_t flow2
Definition: ipv6.h:109
uint8_t hl
Definition: ipv6.h:133
uint8_t ecn
Definition: ipv6.h:123
Definition: ipv6.h:158
static void ipv6_set_flow_label(struct ipv6_hdr *const ipv6, const uint32_t flow_label)
Set the Flow Label of the given IPv6 packet.
Definition: ipv6.h:283
static size_t ipv6_opt_get_length(const struct ipv6_opt *const opt)
get the length (in bytes) of the IPv6 option header
Definition: ipv6.h:297
static void ipv6_set_dscp(struct ipv6_hdr *const ipv6, const uint8_t dscp)
Set the Differentiated Services Code Point (DSCP) of the given IPv6 packet.
Definition: ipv6.h:258
The IPv6 header.
Definition: ipv6.h:88
uint8_t dscp2
Definition: ipv6.h:124
Miscellaneous utils for ROHC libraries.
uint8_t tc2
Definition: ipv6.h:107
static void ipv6_set_dscp_ecn(struct ipv6_hdr *const ipv6, const uint8_t dscp, const uint8_t ecn)
Set the DSCP and ECN of the given IPv6 packet.
Definition: ipv6.h:232
uint8_t version
Definition: ipv6.h:105
#define IPV6_FLOW_MASK
Definition: ipv6.h:95
uint8_t flowl1_
Definition: ipv6.h:122
static uint8_t ipv6_get_dscp(const struct ipv6_hdr *const ipv6)
Get the Differentiated Services Code Point (DSCP) of the given IPv6 packet.
Definition: ipv6.h:246
static uint8_t ipv6_get_tc(const struct ipv6_hdr *const ipv6)
Get the Traffic Class (TC) of the given IPv6 packet.
Definition: ipv6.h:206
uint16_t rohc_hton16(const uint16_t host16)
Convert a 16-bit short integer from host to network byte orders.
Definition: rohc_utils.c:104
uint32_t version_tc_flow
Definition: ipv6.h:92
uint8_t u8[16]
Definition: ipv6.h:69
uint8_t dscp1
Definition: ipv6.h:120
uint32_t u32[4]
Definition: ipv6.h:71
uint16_t plen
Definition: ipv6.h:131
uint8_t length
Definition: ipv6.h:161
uint32_t rohc_ntoh32(const uint32_t net32)
Convert a 32-bit long integer from network to host byte orders.
Definition: rohc_utils.c:55
static void ipv6_set_tc(struct ipv6_hdr *const ipv6, const uint8_t tc)
Set the Traffic Class (TC) of the given IPv6 packet.
Definition: ipv6.h:218
uint8_t version_
Definition: ipv6.h:121
uint8_t tc1
Definition: ipv6.h:104
The IPv6 address.
Definition: ipv6.h:65
uint8_t flow1
Definition: ipv6.h:106
uint8_t nh
Definition: ipv6.h:132
uint16_t u16[8]
Definition: ipv6.h:70