ROHC compression/decompression library
crc.h
Go to the documentation of this file.
1 /*
2  * Copyright 2007,2008 CNES
3  * Copyright 2011,2012,2013 Didier Barvaux
4  * Copyright 2007,2008 Thales Alenia Space
5  * Copyright 2009,2010 Thales Communications
6  * Copyright 2007,2009,2010,2012,2013 Viveris Technologies
7  * Copyright 2012 WBX
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 /**
25  * @file crc.h
26  * @brief ROHC CRC routines
27  * @author Didier Barvaux <didier.barvaux@toulouse.viveris.com>
28  * @author Didier Barvaux <didier@barvaux.org>
29  * @author FWX <rohc_team@dialine.fr>
30  */
31 
32 #ifndef ROHC_COMMON_CRC_H
33 #define ROHC_COMMON_CRC_H
34 
35 #include "ip.h"
36 #include "protocols/udp.h"
37 #include "protocols/rtp.h"
38 #include "protocols/esp.h"
39 #include "protocols/tcp.h"
40 
41 #include <rohc/rohc.h> /* for rohc_profile_t */
42 
43 #include <stdbool.h>
44 
45 /// The CRC-3 initial value
46 #define CRC_INIT_3 0x7
47 /// The CRC-7 initial value
48 #define CRC_INIT_7 0x7f
49 /// The CRC-8 initial value
50 #define CRC_INIT_8 0xff
51 
52 /** The FCS-32 initial value */
53 #define CRC_INIT_FCS32 0xffffffff
54 /** The length (in bytes) of the FCS-32 CRC */
55 #define CRC_FCS32_LEN 4U
56 
57 /** The different types of CRC used to protect ROHC headers */
58 typedef enum
59 {
60  ROHC_CRC_TYPE_NONE = 0, /**< No CRC selected */
61  ROHC_CRC_TYPE_3 = 3, /**< The CRC-3 type */
62  ROHC_CRC_TYPE_7 = 7, /**< The CRC-7 type */
63  ROHC_CRC_TYPE_8 = 8, /**< The CRC-8 type */
65 
66 
67 /*
68  * Function prototypes.
69  */
70 
71 void rohc_crc_init_table(uint8_t *const table,
72  const rohc_crc_type_t crc_type)
73  __attribute__((nonnull(1)));
74 
75 uint8_t crc_calculate(const rohc_crc_type_t crc_type,
76  const uint8_t *const data,
77  const size_t length,
78  const uint8_t init_val,
79  const uint8_t *const crc_table)
80  __attribute__((nonnull(2, 5), warn_unused_result));
81 
82 uint32_t crc_calc_fcs32(const uint8_t *const data,
83  const size_t length,
84  const uint32_t init_val)
85  __attribute__((nonnull(1), warn_unused_result, pure));
86 
87 uint8_t compute_crc_static(const uint8_t *const outer_ip,
88  const uint8_t *const inner_ip,
89  const uint8_t *const next_header,
90  const rohc_crc_type_t crc_type,
91  const uint8_t init_val,
92  const uint8_t *const crc_table)
93  __attribute__((nonnull(1, 6), warn_unused_result));
94 uint8_t compute_crc_dynamic(const uint8_t *const outer_ip,
95  const uint8_t *const inner_ip,
96  const uint8_t *const next_header,
97  const rohc_crc_type_t crc_type,
98  const uint8_t init_val,
99  const uint8_t *const crc_table)
100  __attribute__((nonnull(1, 6), warn_unused_result));
101 
102 static inline
103 uint8_t udp_compute_crc_static(const uint8_t *const outer_ip,
104  const uint8_t *const inner_ip,
105  const uint8_t *const next_header,
106  const rohc_crc_type_t crc_type,
107  const uint8_t init_val,
108  const uint8_t *const crc_table)
109  __attribute__((nonnull(1, 3, 6), warn_unused_result));
110 static inline
111 uint8_t udp_compute_crc_dynamic(const uint8_t *const outer_ip,
112  const uint8_t *const inner_ip,
113  const uint8_t *const next_header,
114  const rohc_crc_type_t crc_type,
115  const uint8_t init_val,
116  const uint8_t *const crc_table)
117  __attribute__((nonnull(1, 3, 6), warn_unused_result));
118 
119 static inline
120 uint8_t esp_compute_crc_static(const uint8_t *const outer_ip,
121  const uint8_t *const inner_ip,
122  const uint8_t *const next_header,
123  const rohc_crc_type_t crc_type,
124  const uint8_t init_val,
125  const uint8_t *const crc_table)
126  __attribute__((nonnull(1, 3, 6), warn_unused_result));
127 static inline
128 uint8_t esp_compute_crc_dynamic(const uint8_t *const outer_ip,
129  const uint8_t *const inner_ip,
130  const uint8_t *const next_header,
131  const rohc_crc_type_t crc_type,
132  const uint8_t init_val,
133  const uint8_t *const crc_table)
134  __attribute__((nonnull(1, 3, 6), warn_unused_result));
135 
136 static inline
137 uint8_t rtp_compute_crc_static(const uint8_t *const outer_ip,
138  const uint8_t *const inner_ip,
139  const uint8_t *const next_header,
140  const rohc_crc_type_t crc_type,
141  const uint8_t init_val,
142  const uint8_t *const crc_table)
143  __attribute__((nonnull(1, 3, 6), warn_unused_result));
144 static inline
145 uint8_t rtp_compute_crc_dynamic(const uint8_t *const outer_ip,
146  const uint8_t *const inner_ip,
147  const uint8_t *const next_header,
148  const rohc_crc_type_t crc_type,
149  const uint8_t init_val,
150  const uint8_t *const crc_table)
151  __attribute__((nonnull(1, 3, 6), warn_unused_result));
152 
153 uint8_t compute_crc_ctrl_fields(const rohc_profile_t profile_id,
154  const uint8_t *const crc_table,
155  const uint8_t reorder_ratio,
156  const uint16_t msn,
157  const uint8_t ip_id_behaviors[],
158  const size_t ip_id_behaviors_nr)
159  __attribute__((nonnull(2), warn_unused_result));
160 
161 
162 /**
163  * @brief Compute the CRC-STATIC part of an UDP or UDP-Lite header
164  *
165  * Concerned fields are:
166  * all fields expect those for CRC-DYNAMIC
167  * - bytes 1-4 in original UDP header
168  *
169  * @param outer_ip The outer IP packet
170  * @param inner_ip The inner IP packet if there is 2 IP headers, NULL otherwise
171  * @param next_header The next header located after the IP header(s)
172  * @param crc_type The type of CRC
173  * @param init_val The initial CRC value
174  * @param crc_table The pre-computed table for fast CRC computation
175  * @return The checksum
176  */
177 static inline
178 uint8_t udp_compute_crc_static(const uint8_t *const outer_ip,
179  const uint8_t *const inner_ip,
180  const uint8_t *const next_header,
181  const rohc_crc_type_t crc_type,
182  const uint8_t init_val,
183  const uint8_t *const crc_table)
184 {
185  uint8_t crc = init_val;
186  const struct udphdr *udp;
187 
188  /* compute the CRC-STATIC value for IP and IP2 headers */
189  crc = compute_crc_static(outer_ip, inner_ip, next_header,
190  crc_type, crc, crc_table);
191 
192  /* get the start of UDP header */
193  udp = (struct udphdr *) next_header;
194 
195  /* bytes 1-4 (Source Port, Destination Port) */
196  crc = crc_calculate(crc_type, (uint8_t *)(&udp->source), 4,
197  crc, crc_table);
198 
199  return crc;
200 }
201 
202 
203 /**
204  * @brief Compute the CRC-DYNAMIC part of an UDP or UDP-Lite header
205  *
206  * Concerned fields are:
207  * - bytes 5-6, 7-8 in original UDP header
208  *
209  * @param outer_ip The outer IP packet
210  * @param inner_ip The inner IP packet if there is 2 IP headers, NULL otherwise
211  * @param next_header The next header located after the IP header(s)
212  * @param crc_type The type of CRC
213  * @param init_val The initial CRC value
214  * @param crc_table The pre-computed table for fast CRC computation
215  * @return The checksum
216  */
217 static inline
218 uint8_t udp_compute_crc_dynamic(const uint8_t *const outer_ip,
219  const uint8_t *const inner_ip,
220  const uint8_t *const next_header,
221  const rohc_crc_type_t crc_type,
222  const uint8_t init_val,
223  const uint8_t *const crc_table)
224 {
225  uint8_t crc = init_val;
226  const struct udphdr *udp;
227 
228  /* compute the CRC-DYNAMIC value for IP and IP2 headers */
229  crc = compute_crc_dynamic(outer_ip, inner_ip, next_header,
230  crc_type, crc, crc_table);
231 
232  /* get the start of UDP header */
233  udp = (struct udphdr *) next_header;
234 
235  /* bytes 5-8 (Length, Checksum) */
236  crc = crc_calculate(crc_type, (uint8_t *)(&udp->len), 4,
237  crc, crc_table);
238 
239  return crc;
240 }
241 
242 
243 /**
244  * @brief Compute the CRC-STATIC part of an ESP header
245  *
246  * Concerned fields are:
247  * all fields expect those for CRC-DYNAMIC
248  * - bytes 1-4 in original ESP header
249  *
250  * @param outer_ip The outer IP packet
251  * @param inner_ip The inner IP packet if there is 2 IP headers, NULL otherwise
252  * @param next_header The next header located after the IP header(s)
253  * @param crc_type The type of CRC
254  * @param init_val The initial CRC value
255  * @param crc_table The pre-computed table for fast CRC computation
256  * @return The checksum
257  */
258 static inline
259 uint8_t esp_compute_crc_static(const uint8_t *const outer_ip,
260  const uint8_t *const inner_ip,
261  const uint8_t *const next_header,
262  const rohc_crc_type_t crc_type,
263  const uint8_t init_val,
264  const uint8_t *const crc_table)
265 {
266  uint8_t crc = init_val;
267  const struct esphdr *esp;
268 
269  /* compute the CRC-STATIC value for IP and IP2 headers */
270  crc = compute_crc_static(outer_ip, inner_ip, next_header,
271  crc_type, crc, crc_table);
272 
273  /* get the start of ESP header */
274  esp = (struct esphdr *) next_header;
275 
276  /* bytes 1-4 (Security parameters index) */
277  crc = crc_calculate(crc_type, (uint8_t *)(&esp->spi), 4,
278  crc, crc_table);
279 
280  return crc;
281 }
282 
283 
284 /**
285  * @brief Compute the CRC-DYNAMIC part of an ESP header
286  *
287  * Concerned fields are:
288  * - bytes 5-8 in original ESP header
289  *
290  * @param outer_ip The outer IP packet
291  * @param inner_ip The inner IP packet if there is 2 IP headers, NULL otherwise
292  * @param next_header The next header located after the IP header(s)
293  * @param crc_type The type of CRC
294  * @param init_val The initial CRC value
295  * @param crc_table The pre-computed table for fast CRC computation
296  * @return The checksum
297  */
298 static inline
299 uint8_t esp_compute_crc_dynamic(const uint8_t *const outer_ip,
300  const uint8_t *const inner_ip,
301  const uint8_t *const next_header,
302  const rohc_crc_type_t crc_type,
303  const uint8_t init_val,
304  const uint8_t *const crc_table)
305 {
306  uint8_t crc = init_val;
307  const struct esphdr *esp;
308 
309  /* compute the CRC-DYNAMIC value for IP and IP2 headers */
310  crc = compute_crc_dynamic(outer_ip, inner_ip, next_header,
311  crc_type, crc, crc_table);
312 
313  /* get the start of ESP header */
314  esp = (struct esphdr *) next_header;
315 
316  /* bytes 5-8 (Sequence number) */
317  crc = crc_calculate(crc_type, (uint8_t *)(&esp->sn), 4,
318  crc, crc_table);
319 
320  return crc;
321 }
322 
323 
324 /**
325  * @brief Compute the CRC-STATIC part of a RTP header
326  *
327  * Concerned fields are:
328  * all fields expect those for CRC-DYNAMIC
329  * - bytes 1, 9-12 (and CSRC list) in original RTP header
330  *
331  * @param outer_ip The outer IP packet
332  * @param inner_ip The inner IP packet if there is 2 IP headers, NULL otherwise
333  * @param next_header The next header located after the IP header(s)
334  * @param crc_type The type of CRC
335  * @param init_val The initial CRC value
336  * @param crc_table The pre-computed table for fast CRC computation
337  * @return The checksum
338  */
339 static inline
340 uint8_t rtp_compute_crc_static(const uint8_t *const outer_ip,
341  const uint8_t *const inner_ip,
342  const uint8_t *const next_header,
343  const rohc_crc_type_t crc_type,
344  const uint8_t init_val,
345  const uint8_t *const crc_table)
346 {
347  uint8_t crc = init_val;
348  const struct rtphdr *rtp;
349 
350  /* compute the CRC-STATIC value for IP, IP2 and UDP headers */
351  crc = udp_compute_crc_static(outer_ip, inner_ip, next_header,
352  crc_type, crc, crc_table);
353 
354  /* get the start of RTP header */
355  rtp = (struct rtphdr *) (next_header + sizeof(struct udphdr));
356 
357  /* byte 1 (Version, P, X, CC) */
358  crc = crc_calculate(crc_type, (uint8_t *)rtp, 1, crc, crc_table);
359 
360  /* bytes 9-12 (SSRC identifier) */
361  crc = crc_calculate(crc_type, (uint8_t *)(&rtp->ssrc), 4,
362  crc, crc_table);
363 
364  /* TODO: CSRC identifiers */
365 
366  return crc;
367 }
368 
369 
370 /**
371  * @brief Compute the CRC-DYNAMIC part of a RTP header
372  *
373  * Concerned fields are:
374  * - bytes 2, 3-4, 5-8 in original RTP header
375  *
376  * @param outer_ip The outer IP packet
377  * @param inner_ip The inner IP packet if there is 2 IP headers, NULL otherwise
378  * @param next_header The next header located after the IP header(s)
379  * @param crc_type The type of CRC
380  * @param init_val The initial CRC value
381  * @param crc_table The pre-computed table for fast CRC computation
382  * @return The checksum
383  */
384 static inline
385 uint8_t rtp_compute_crc_dynamic(const uint8_t *const outer_ip,
386  const uint8_t *const inner_ip,
387  const uint8_t *const next_header,
388  const rohc_crc_type_t crc_type,
389  const uint8_t init_val,
390  const uint8_t *const crc_table)
391 {
392  uint8_t crc = init_val;
393  const struct rtphdr *rtp;
394 
395  /* compute the CRC-DYNAMIC value for IP, IP2 and UDP headers */
396  crc = udp_compute_crc_dynamic(outer_ip, inner_ip, next_header,
397  crc_type, crc, crc_table);
398 
399  /* get the start of RTP header */
400  rtp = (struct rtphdr *) (next_header + sizeof(struct udphdr));
401 
402  /* bytes 2-8 (Marker, Payload Type, Sequence Number, Timestamp) */
403  crc = crc_calculate(crc_type, ((uint8_t *) rtp) + 1, 7,
404  crc, crc_table);
405 
406  return crc;
407 }
408 
409 
410 
411 #endif
412 
uint16_t len
Definition: udp.h:42
IP-agnostic packet.
uint8_t crc_calculate(const rohc_crc_type_t crc_type, const uint8_t *const data, const size_t length, const uint8_t init_val, const uint8_t *const crc_table)
Calculate the checksum for the given data.
Definition: crc.c:220
uint8_t compute_crc_ctrl_fields(const rohc_profile_t profile_id, const uint8_t *const crc_table, const uint8_t reorder_ratio, const uint16_t msn, const uint8_t ip_id_behaviors[], const size_t ip_id_behaviors_nr)
Compute the CRC-3 over control fields for ROHCv2 profiles.
Definition: crc.c:464
ESP header description.
uint32_t sn
Definition: esp.h:43
Definition: udp.h:38
uint32_t spi
Definition: esp.h:42
uint8_t compute_crc_static(const uint8_t *const outer_ip, const uint8_t *const inner_ip, const uint8_t *const next_header, const rohc_crc_type_t crc_type, const uint8_t init_val, const uint8_t *const crc_table)
Compute the CRC-STATIC part of an IP header.
Definition: crc.c:295
The RTP header.
Definition: rtp.h:48
static uint8_t esp_compute_crc_dynamic(const uint8_t *const outer_ip, const uint8_t *const inner_ip, const uint8_t *const next_header, const rohc_crc_type_t crc_type, const uint8_t init_val, const uint8_t *const crc_table)
Compute the CRC-DYNAMIC part of an ESP header.
Definition: crc.h:299
static uint8_t udp_compute_crc_static(const uint8_t *const outer_ip, const uint8_t *const inner_ip, const uint8_t *const next_header, const rohc_crc_type_t crc_type, const uint8_t init_val, const uint8_t *const crc_table)
Compute the CRC-STATIC part of an UDP or UDP-Lite header.
Definition: crc.h:178
Definition: crc.h:62
rohc_crc_type_t
Definition: crc.h:58
uint8_t compute_crc_dynamic(const uint8_t *const outer_ip, const uint8_t *const inner_ip, const uint8_t *const next_header, const rohc_crc_type_t crc_type, const uint8_t init_val, const uint8_t *const crc_table)
Compute the CRC-DYNAMIC part of an IP header.
Definition: crc.c:388
Definition: crc.h:61
static uint8_t rtp_compute_crc_dynamic(const uint8_t *const outer_ip, const uint8_t *const inner_ip, const uint8_t *const next_header, const rohc_crc_type_t crc_type, const uint8_t init_val, const uint8_t *const crc_table)
Compute the CRC-DYNAMIC part of a RTP header.
Definition: crc.h:385
static uint8_t udp_compute_crc_dynamic(const uint8_t *const outer_ip, const uint8_t *const inner_ip, const uint8_t *const next_header, const rohc_crc_type_t crc_type, const uint8_t init_val, const uint8_t *const crc_table)
Compute the CRC-DYNAMIC part of an UDP or UDP-Lite header.
Definition: crc.h:218
RTP header.
Definition: esp.h:40
Definition: crc.h:60
void rohc_crc_init_table(uint8_t *const table, const rohc_crc_type_t crc_type)
Initialize a CRC table given a 256-byte table and the CRC type to use.
Definition: crc.c:176
static uint8_t esp_compute_crc_static(const uint8_t *const outer_ip, const uint8_t *const inner_ip, const uint8_t *const next_header, const rohc_crc_type_t crc_type, const uint8_t init_val, const uint8_t *const crc_table)
Compute the CRC-STATIC part of an ESP header.
Definition: crc.h:259
Definition: crc.h:63
RTP header.
static uint8_t rtp_compute_crc_static(const uint8_t *const outer_ip, const uint8_t *const inner_ip, const uint8_t *const next_header, const rohc_crc_type_t crc_type, const uint8_t init_val, const uint8_t *const crc_table)
Compute the CRC-STATIC part of a RTP header.
Definition: crc.h:340
rohc_profile_t
The different ROHC compression/decompression profiles.
Definition: rohc_profiles.h:70
uint16_t source
Definition: udp.h:40
TCP header description.
Defines the UDP header.
uint32_t crc_calc_fcs32(const uint8_t *const data, const size_t length, const uint32_t init_val)
Optimized CRC FCS-32 calculation using a table.
Definition: crc.c:260