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
00026
00027 #ifndef ROHC_COMMON_IP_H
00028 #define ROHC_COMMON_IP_H
00029
00030 #include "protocols/ipv4.h"
00031 #include "protocols/ipv6.h"
00032
00033 #include <stdlib.h>
00034 #include <stdint.h>
00035 #ifdef __KERNEL__
00036 # include <linux/types.h>
00037 #else
00038 # include <stdbool.h>
00039 #endif
00040
00041
00042
00043 typedef enum
00044 {
00045 ROHC_IP_HDR_NONE = 0,
00046 ROHC_IP_HDR_FIRST = 1,
00047 ROHC_IP_HDR_SECOND = 2,
00048
00049 } ip_header_pos_t;
00050
00051
00052
00053 typedef enum
00054 {
00055
00056 IPV4 = 4,
00057
00058 IPV6 = 6,
00059
00060 IP_UNKNOWN = 0,
00061
00062 IPV4_MALFORMED = 1,
00063
00064 IPV6_MALFORMED = 2,
00065 } ip_version;
00066
00067
00068
00069 struct net_hdr
00070 {
00071 uint8_t proto;
00072 uint8_t *data;
00073 size_t len;
00074 };
00075
00076
00077
00078
00079
00080
00081 struct ip_packet
00082 {
00083
00084 ip_version version;
00085
00086
00087 union
00088 {
00089
00090 struct ipv4_hdr v4;
00091
00092 struct ipv6_hdr v6;
00093 } header;
00094
00095
00096 const uint8_t *data;
00097
00098
00099 size_t size;
00100
00101 struct net_hdr nh;
00102 struct net_hdr nl;
00103 };
00104
00105
00106
00107
00108
00109
00110 #ifndef __KERNEL__
00111
00112 static inline uint16_t swab16(const uint16_t value)
00113 __attribute__((warn_unused_result, const));
00114
00115
00116
00117
00118
00119
00120
00121 static inline uint16_t swab16(const uint16_t value)
00122 {
00123 return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8);
00124 }
00125
00126
00127 #if defined(__i386__) || defined(__x86_64__)
00128
00129 static inline uint16_t ip_fast_csum(const uint8_t *iph,
00130 const size_t ihl)
00131 __attribute__((nonnull(1), warn_unused_result, pure));
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 static inline uint16_t ip_fast_csum(const uint8_t *iph,
00145 const size_t ihl)
00146 {
00147 uint32_t __ihl = ihl;
00148 uint32_t sum;
00149
00150 __asm__ __volatile__(
00151 " \n\
00152 movl (%1), %0 \n\
00153 subl $4, %2 \n\
00154 jbe 2f \n\
00155 addl 4(%1), %0 \n\
00156 adcl 8(%1), %0 \n\
00157 adcl 12(%1), %0 \n\
00158 1: adcl 16(%1), %0 \n\
00159 lea 4(%1), %1 \n\
00160 decl %2 \n\
00161 jne 1b \n\
00162 adcl $0, %0 \n\
00163 movl %0, %2 \n\
00164 shrl $16, %0 \n\
00165 addw %w2, %w0 \n\
00166 adcl $0, %0 \n\
00167 notl %0 \n\
00168 2: \n\
00169 "
00170
00171
00172
00173 : "=r" (sum), "=r" (iph), "=r" (__ihl)
00174 : "1" (iph), "2" (__ihl)
00175 : "memory");
00176
00177 return (uint16_t) (sum & 0xffff);
00178 }
00179
00180
00181 #else
00182
00183 static inline uint16_t from32to16(const uint32_t x)
00184 __attribute__((warn_unused_result, const));
00185
00186 static inline uint16_t from32to16(const uint32_t x)
00187 {
00188 uint32_t y;
00189
00190 y = (x & 0xffff) + (x >> 16);
00191
00192 y = (y & 0xffff) + (y >> 16);
00193 return y;
00194 }
00195
00196 static inline uint16_t ip_fast_csum(const uint8_t *const iph,
00197 const size_t ihl)
00198 __attribute__((nonnull(1), warn_unused_result, pure));
00199
00200
00201
00202
00203
00204 static inline uint16_t ip_fast_csum(const uint8_t *const iph,
00205 const size_t ihl)
00206 {
00207 const uint8_t *buff = iph;
00208 size_t len = ihl * 4;
00209 bool odd;
00210 size_t count;
00211 uint32_t result = 0;
00212
00213 if(len == 0)
00214 {
00215 goto out;
00216 }
00217 odd = 1 & (uintptr_t) buff;
00218 if(odd)
00219 {
00220 #ifdef __LITTLE_ENDIAN
00221 result = *buff;
00222 #else
00223 result += (*buff << 8);
00224 #endif
00225 len--;
00226 buff++;
00227 }
00228 count = len >> 1;
00229 if(count)
00230 {
00231 if(2 & (uintptr_t) buff)
00232 {
00233 result += *(uint16_t *) buff;
00234 count--;
00235 len -= 2;
00236 buff += 2;
00237 }
00238 count >>= 1;
00239 if(count)
00240 {
00241 uint32_t carry = 0;
00242 do
00243 {
00244 uint32_t word = *(uint32_t *) buff;
00245 count--;
00246 buff += sizeof(uint32_t);
00247 result += carry;
00248 result += word;
00249 carry = (word > result);
00250 }
00251 while(count);
00252 result += carry;
00253 result = (result & 0xffff) + (result >> 16);
00254 }
00255 if(len & 2)
00256 {
00257 result += *(uint16_t *) buff;
00258 buff += 2;
00259 }
00260 }
00261 if(len & 1)
00262 {
00263 #ifdef __LITTLE_ENDIAN
00264 result += *buff;
00265 #else
00266 result += (*buff << 8);
00267 #endif
00268 }
00269 result = from32to16(result);
00270 if(odd)
00271 {
00272 result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
00273 }
00274 out:
00275 return ~result;
00276 }
00277
00278
00279 #endif
00280
00281 #else
00282 # include <asm/checksum.h>
00283 #endif
00284
00285
00286
00287
00288
00289
00290
00291
00292 bool ip_create(struct ip_packet *const ip,
00293 const uint8_t *const packet,
00294 const size_t size)
00295 __attribute__((warn_unused_result, nonnull(1, 2)));
00296 bool ip_get_inner_packet(const struct ip_packet *const outer,
00297 struct ip_packet *const inner)
00298 __attribute__((warn_unused_result, nonnull(1, 2)));
00299
00300 const uint8_t * ip_get_raw_data(const struct ip_packet *const ip)
00301 __attribute__((warn_unused_result, nonnull(1), pure));
00302 uint8_t * ip_get_next_header(const struct ip_packet *const ip,
00303 uint8_t *const type)
00304 __attribute__((warn_unused_result, nonnull(1, 2)));
00305 uint8_t * ip_get_next_layer(const struct ip_packet *const ip)
00306 __attribute__((warn_unused_result, nonnull(1)));
00307 uint8_t * ip_get_next_ext_from_ip(const struct ip_packet *const ip,
00308 uint8_t *const type)
00309 __attribute__((warn_unused_result, nonnull(1, 2)));
00310 uint8_t * ip_get_next_ext_from_ext(const uint8_t *const ext,
00311 uint8_t *const type)
00312 __attribute__((warn_unused_result, nonnull(1, 2)));
00313
00314 unsigned int ip_get_totlen(const struct ip_packet *const ip)
00315 __attribute__((warn_unused_result, nonnull(1), pure));
00316 unsigned int ip_get_hdrlen(const struct ip_packet *const ip)
00317 __attribute__((warn_unused_result, nonnull(1)));
00318
00319 bool ip_is_fragment(const struct ip_packet *const ip)
00320 __attribute__((warn_unused_result, nonnull(1), pure));
00321 ip_version ip_get_version(const struct ip_packet *const ip)
00322 __attribute__((warn_unused_result, nonnull(1), pure));
00323 uint8_t ip_get_protocol(const struct ip_packet *const ip)
00324 __attribute__((warn_unused_result, nonnull(1), pure));
00325 unsigned int ip_get_tos(const struct ip_packet *const ip)
00326 __attribute__((warn_unused_result, nonnull(1), pure));
00327 unsigned int ip_get_ttl(const struct ip_packet *const ip)
00328 __attribute__((warn_unused_result, nonnull(1), pure));
00329
00330 void ip_set_version(struct ip_packet *const ip, const ip_version value)
00331 __attribute__((nonnull(1)));
00332 void ip_set_protocol(struct ip_packet *const ip, const uint8_t value)
00333 __attribute__((nonnull(1)));
00334 void ip_set_tos(struct ip_packet *const ip, const uint8_t value)
00335 __attribute__((nonnull(1)));
00336 void ip_set_ttl(struct ip_packet *const ip, const uint8_t value)
00337 __attribute__((nonnull(1)));
00338 void ip_set_saddr(struct ip_packet *const ip, const uint8_t *value)
00339 __attribute__((nonnull(1, 2)));
00340 void ip_set_daddr(struct ip_packet *const ip, const uint8_t *value)
00341 __attribute__((nonnull(1, 2)));
00342
00343
00344
00345 const struct ipv4_hdr * ipv4_get_header(const struct ip_packet *const ip)
00346 __attribute__((warn_unused_result, nonnull(1), pure));
00347 uint16_t ipv4_get_id(const struct ip_packet *const ip)
00348 __attribute__((warn_unused_result, nonnull(1), pure));
00349 uint16_t ipv4_get_id_nbo(const struct ip_packet *const ip, const unsigned int nbo)
00350 __attribute__((warn_unused_result, nonnull(1), pure));
00351 int ipv4_get_df(const struct ip_packet *const ip)
00352 __attribute__((warn_unused_result, nonnull(1), pure));
00353 uint32_t ipv4_get_saddr(const struct ip_packet *const ip)
00354 __attribute__((warn_unused_result, nonnull(1), pure));
00355 uint32_t ipv4_get_daddr(const struct ip_packet *const ip)
00356 __attribute__((warn_unused_result, nonnull(1), pure));
00357
00358 void ipv4_set_id(struct ip_packet *const ip, const int value)
00359 __attribute__((nonnull(1)));
00360 void ipv4_set_df(struct ip_packet *const ip, const int value)
00361 __attribute__((nonnull(1)));
00362
00363
00364
00365 const struct ipv6_hdr * ipv6_get_header(const struct ip_packet *const ip)
00366 __attribute__((warn_unused_result, nonnull(1), pure));
00367 uint32_t ip_get_flow_label(const struct ip_packet *const ip)
00368 __attribute__((warn_unused_result, nonnull(1), pure));
00369 const struct ipv6_addr * ipv6_get_saddr(const struct ip_packet *const ip)
00370 __attribute__((warn_unused_result, nonnull(1), pure));
00371 const struct ipv6_addr * ipv6_get_daddr(const struct ip_packet *const ip)
00372 __attribute__((warn_unused_result, nonnull(1), pure));
00373 void ip_set_flow_label(struct ip_packet *const ip, const uint32_t value)
00374 __attribute__((nonnull(1)));
00375 unsigned short ip_get_extension_size(const uint8_t *const ext)
00376 __attribute__((warn_unused_result, nonnull(1), pure));
00377 unsigned short ip_get_total_extension_size(const struct ip_packet *const ip)
00378 __attribute__((warn_unused_result, nonnull(1)));
00379
00380
00381 #endif
00382