00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef ROHC_PROTOCOLS_IPV6_H
00026 #define ROHC_PROTOCOLS_IPV6_H
00027
00028 #include "rohc_utils.h"
00029
00030 #include <stdint.h>
00031 #include <stddef.h>
00032
00033 #ifdef __KERNEL__
00034 # include <endian.h>
00035 #else
00036 # include "config.h"
00037 #endif
00038
00039
00040
00041 #define IPV6_ADDR_FORMAT \
00042 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
00043
00044
00045
00046 #define IPV6_ADDR_IN6(x) \
00047 IPV6_ADDR_RAW((x)->u8)
00048
00049
00050
00051 #define IPV6_ADDR_RAW(x) \
00052 (x)[0], (x)[1], (x)[2], (x)[3], (x)[4], (x)[5], (x)[6], (x)[7], \
00053 (x)[8], (x)[9], (x)[10], (x)[11], (x)[12], (x)[13], (x)[14], (x)[15]
00054
00055
00056
00057 #define IPV6_ADDR_CMP(x, y) \
00058 ((x)->u32[0] == (y)->u32[0] && (x)->u32[1] == (y)->u32[1] && \
00059 (x)->u32[2] == (y)->u32[2] && (x)->u32[3] == (y)->u32[3])
00060
00061
00062
00063
00064
00065 struct ipv6_addr
00066 {
00067 union
00068 {
00069 uint8_t u8[16];
00070 uint16_t u16[8];
00071 uint32_t u32[4];
00072 } __attribute__((packed));
00073 } __attribute__((packed));
00074
00075
00076
00077 #if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
00078 (defined(__GNUC__) && defined(__GNUC_MINOR__) && \
00079 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))))
00080 _Static_assert(sizeof(struct ipv6_addr) == 16,
00081 "IPv6 address should exactly 16-byte long");
00082 #endif
00083
00084
00085
00086
00087
00088 struct ipv6_hdr
00089 {
00090 union
00091 {
00092 uint32_t version_tc_flow;
00093 #define IPV6_VERSION_MASK 0xf0000000U
00094 #define IPV6_TC_MASK 0x0ff00000U
00095 #define IPV6_FLOW_MASK 0x000fffffU
00096 struct
00097 {
00098 #if WORDS_BIGENDIAN == 1
00099 uint8_t version:4;
00100 uint8_t tc1:4;
00101 uint8_t tc2:4;
00102 uint8_t flowl1:4;
00103 #else
00104 uint8_t tc1:4;
00105 uint8_t version:4;
00106 uint8_t flow1:4;
00107 uint8_t tc2:4;
00108 #endif
00109 uint16_t flow2;
00110 } __attribute__((packed));
00111 struct
00112 {
00113 #if WORDS_BIGENDIAN == 1
00114 uint8_t version_:4;
00115 uint8_t dscp1:4;
00116 uint8_t dscp2:2;
00117 uint8_t ecn:2;
00118 uint8_t flowl1_:4;
00119 #else
00120 uint8_t dscp1:4;
00121 uint8_t version_:4;
00122 uint8_t flowl1_:4;
00123 uint8_t ecn:2;
00124 uint8_t dscp2:2;
00125 #endif
00126 uint16_t flow2_;
00127 } __attribute__((packed));
00128
00129 } __attribute__((packed));
00130
00131 uint16_t plen;
00132 uint8_t nh;
00133 uint8_t hl;
00134 struct ipv6_addr saddr;
00135 struct ipv6_addr daddr;
00136
00137 } __attribute__((packed));
00138
00139
00140
00141 #if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
00142 (defined(__GNUC__) && defined(__GNUC_MINOR__) && \
00143 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))))
00144 _Static_assert(sizeof(struct ipv6_hdr) == 40,
00145 "IPv6 header should exactly 40-byte long");
00146 #endif
00147
00148
00149
00150 #define IPV6_OPT_HDR_LEN_FIELD_MAX_VAL 0xffU
00151
00152 #define IPV6_OPT_HDR_LEN_MAX ((IPV6_OPT_HDR_LEN_FIELD_MAX_VAL + 1) * 8)
00153
00154 #define IPV6_OPT_CTXT_LEN_MAX (IPV6_OPT_HDR_LEN_MAX - 2)
00155
00156
00157
00158 struct ipv6_opt
00159 {
00160 uint8_t next_header;
00161 uint8_t length;
00162 uint8_t value[1];
00163 } __attribute__((packed));
00164
00165
00166
00167 #if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
00168 (defined(__GNUC__) && defined(__GNUC_MINOR__) && \
00169 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))))
00170 _Static_assert(sizeof(struct ipv6_opt) == 3,
00171 "IPv6 option header should exactly 3-byte long");
00172 #endif
00173
00174
00175 static inline uint8_t ipv6_get_tc(const struct ipv6_hdr *const ipv6)
00176 __attribute__((warn_unused_result, nonnull(1), pure));
00177 static inline void ipv6_set_tc(struct ipv6_hdr *const ipv6, const uint8_t tc)
00178 __attribute__((nonnull(1)));
00179
00180 static inline void ipv6_set_dscp_ecn(struct ipv6_hdr *const ipv6,
00181 const uint8_t dscp,
00182 const uint8_t ecn)
00183 __attribute__((nonnull(1)));
00184
00185 static inline uint8_t ipv6_get_dscp(const struct ipv6_hdr *const ipv6)
00186 __attribute__((warn_unused_result, nonnull(1), pure));
00187 static inline void ipv6_set_dscp(struct ipv6_hdr *const ipv6, const uint8_t dscp)
00188 __attribute__((nonnull(1)));
00189
00190 static inline uint32_t ipv6_get_flow_label(const struct ipv6_hdr *const ipv6)
00191 __attribute__((warn_unused_result, nonnull(1), pure));
00192 static inline void ipv6_set_flow_label(struct ipv6_hdr *const ipv6,
00193 const uint32_t flow_label)
00194 __attribute__((nonnull(1)));
00195
00196 static inline size_t ipv6_opt_get_length(const struct ipv6_opt *const opt)
00197 __attribute__((warn_unused_result, nonnull(1), pure));
00198
00199
00200
00201
00202
00203
00204
00205
00206 static inline uint8_t ipv6_get_tc(const struct ipv6_hdr *const ipv6)
00207 {
00208 return ((ipv6->tc1 << 4) | ipv6->tc2);
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218 static inline void ipv6_set_tc(struct ipv6_hdr *const ipv6, const uint8_t tc)
00219 {
00220 ipv6->tc1 = (tc >> 4) & 0x0f;
00221 ipv6->tc2 = tc & 0x0f;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 static inline void ipv6_set_dscp_ecn(struct ipv6_hdr *const ipv6,
00233 const uint8_t dscp,
00234 const uint8_t ecn)
00235 {
00236 ipv6_set_tc(ipv6, ((dscp << 2) & 0xfc) | (ecn & 0x03));
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246 static inline uint8_t ipv6_get_dscp(const struct ipv6_hdr *const ipv6)
00247 {
00248 return ((ipv6->dscp1 << 2) | ipv6->dscp2);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 static inline void ipv6_set_dscp(struct ipv6_hdr *const ipv6, const uint8_t dscp)
00259 {
00260 ipv6->dscp1 = (dscp >> 2) & 0x0f;
00261 ipv6->dscp2 = dscp & 0x03;
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271 static inline uint32_t ipv6_get_flow_label(const struct ipv6_hdr *const ipv6)
00272 {
00273 return (rohc_ntoh32(ipv6->version_tc_flow) & IPV6_FLOW_MASK);
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283 static inline void ipv6_set_flow_label(struct ipv6_hdr *const ipv6,
00284 const uint32_t flow_label)
00285 {
00286 ipv6->flow1 = (flow_label >> 16);
00287 ipv6->flow2 = rohc_hton16(flow_label & 0xffff);
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297 static inline size_t ipv6_opt_get_length(const struct ipv6_opt *const opt)
00298 {
00299 return ((opt->length + 1) * 8);
00300 }
00301
00302
00303 #endif
00304