ROHC compression/decompression library
tcp.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2012,2013,2014 Didier Barvaux
00003  * Copyright 2013 Viveris Technologies
00004  * Copyright 2012 WBX
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 /**
00022  * @file   tcp.h
00023  * @brief  TCP header description.
00024  * @author FWX <rohc_team@dialine.fr>
00025  * @author Didier Barvaux <didier@barvaux.org>
00026  * @author Didier Barvaux <didier.barvaux@toulouse.viveris.com>
00027  */
00028 
00029 #ifndef ROHC_PROTOCOLS_TCP_H
00030 #define ROHC_PROTOCOLS_TCP_H
00031 
00032 #include <stdint.h>
00033 
00034 #ifdef __KERNEL__
00035 #       include <endian.h>
00036 #else
00037 #       include "config.h" /* for WORDS_BIGENDIAN */
00038 #endif
00039 
00040 
00041 /* See RFC4996 page 37-40 */
00042 
00043 #define ROHC_PACKET_TYPE_IR      0xFD
00044 #define ROHC_PACKET_TYPE_IR_DYN  0xF8
00045 
00046 /**
00047  * @brief Define the IPv6 option header.
00048  *
00049  */
00050 
00051 typedef struct __attribute__((packed)) ipv6_opt
00052 {
00053         uint8_t next_header;
00054         uint8_t length;
00055         uint8_t value[1];
00056 } ipv6_opt_t;
00057 
00058 /**
00059  * @brief Define the static part of IPv6 option header.
00060  *
00061  */
00062 
00063 typedef struct __attribute__((packed)) ip_opt_static
00064 {
00065         uint8_t next_header;
00066         uint8_t length;
00067 } ip_opt_static_t;
00068 
00069 /**
00070  * @brief Define the dynamic part of IPv6 option header.
00071  *
00072  */
00073 
00074 typedef struct __attribute__((packed)) ip_opt_dynamic
00075 {
00076         uint8_t value[1];
00077 } ip_opt_dynamic_t;
00078 
00079 /**
00080  * @brief Define the IPv6 Destination options header
00081  *
00082  */
00083 
00084 typedef struct __attribute__((packed)) ip_dest_opt
00085 {
00086         uint8_t next_header;
00087         uint8_t length;
00088         uint8_t value[1];
00089 } ip_dest_opt_t;
00090 
00091 /**
00092  * @brief Define the static part of IPv6 Destination option header.
00093  *
00094  */
00095 
00096 typedef struct __attribute__((packed)) ip_dest_opt_static
00097 {
00098         uint8_t next_header;
00099         uint8_t length;
00100 } ip_dest_opt_static_t;
00101 
00102 /**
00103  * @brief Define the dynamic part of IPv6 Destination option header.
00104  *
00105  */
00106 
00107 typedef struct __attribute__((packed)) ip_dest_opt_dynamic
00108 {
00109         uint8_t value[1];
00110 } ip_dest_opt_dynamic_t;
00111 
00112 /**
00113  * @brief Define the IPv6 Hop-by-Hop option header.
00114  *
00115  */
00116 
00117 typedef struct __attribute__((packed)) ip_hop_opt
00118 {
00119         uint8_t next_header;
00120         uint8_t length;
00121         uint8_t value[1];
00122 } ip_hop_opt_t;
00123 
00124 /**
00125  * @brief Define the static part of IPv6 Hop-by-Hop option header.
00126  *
00127  */
00128 
00129 typedef struct __attribute__((packed)) ip_hop_opt_static
00130 {
00131         uint8_t next_header;
00132         uint8_t length;
00133 } ip_hop_opt_static_t;
00134 
00135 /**
00136  * @brief Define the dynamic part of IPv6 Hop-by-Hop option header.
00137  *
00138  */
00139 
00140 typedef struct __attribute__((packed)) ip_hop_opt_dynamic
00141 {
00142         uint8_t value[1];
00143 } ip_hop_opt_dynamic_t;
00144 
00145 /**
00146  * @brief Define the IPv6 Routing option header.
00147  *
00148  */
00149 
00150 typedef struct __attribute__((packed)) ip_rout_opt
00151 {
00152         uint8_t next_header;
00153         uint8_t length;
00154         uint8_t value[1];
00155 } ip_rout_opt_t;
00156 
00157 /**
00158  * @brief Define the static part of IPv6 Routing option header.
00159  *
00160  */
00161 
00162 typedef struct __attribute__((packed)) ip_rout_opt_static
00163 {
00164         uint8_t next_header;
00165         uint8_t length;
00166         uint8_t value[1];
00167 } ip_rout_opt_static_t;
00168 
00169 /**
00170  * @brief Define the IPv6 GRE option header.
00171  *
00172  * See RFC5225 page 55
00173  */
00174 
00175 typedef struct __attribute__((packed)) ip_gre_opt
00176 {
00177 #if WORDS_BIGENDIAN != 1
00178         uint8_t reserved2 : 4;
00179         uint8_t s_flag : 1;
00180         uint8_t k_flag : 1;
00181         uint8_t r_flag : 1;
00182         uint8_t c_flag : 1;
00183 
00184         uint8_t version : 3;
00185         uint8_t reserved1 : 5;
00186 #else
00187         uint16_t c_flag : 1;
00188         uint16_t r_flag : 1;
00189         uint16_t k_flag : 1;
00190         uint16_t s_flag : 1;
00191         uint16_t reserved0 : 9;
00192         uint16_t version : 3;
00193 #endif
00194         uint16_t protocol;
00195         uint32_t datas[1];
00196 } ip_gre_opt_t;
00197 
00198 /**
00199  * @brief Define the static part of IPv6 GRE option header.
00200  *
00201  */
00202 
00203 typedef struct __attribute__((packed)) ip_gre_opt_static
00204 {
00205 #if WORDS_BIGENDIAN != 1
00206         uint8_t padding : 4;
00207         uint8_t s_flag : 1;
00208         uint8_t k_flag : 1;
00209         uint8_t c_flag : 1;
00210         uint8_t protocol : 1;
00211 #else
00212         uint8_t protocol : 1;
00213         uint8_t c_flag : 1;
00214         uint8_t k_flag : 1;
00215         uint8_t s_flag : 1;
00216         uint8_t padding : 4;
00217 #endif
00218         uint8_t options[0];     // if k_flag
00219 } ip_gre_opt_static_t;
00220 
00221 /**
00222  * @brief Define the IPv6 MIME option header.
00223  *
00224  */
00225 
00226 typedef struct __attribute__((packed)) ip_mime_opt
00227 {
00228         uint8_t next_header;
00229 #if WORDS_BIGENDIAN != 1
00230         uint8_t res_bits : 7;
00231         uint8_t s_bit : 1;
00232 #else
00233         uint8_t s_bit : 1;
00234         uint8_t res_bits : 7;
00235 #endif
00236         uint16_t checksum;
00237         uint32_t orig_dest;
00238         uint32_t orig_src;         // if s_bit set
00239 } ip_mime_opt_t;
00240 
00241 /**
00242  * @brief Define the static part of IPv6 MIME option header.
00243  *
00244  */
00245 
00246 typedef struct __attribute__((packed)) ip_mime_opt_static
00247 {
00248         uint8_t next_header;
00249 #if WORDS_BIGENDIAN != 1
00250         uint8_t res_bits : 7;
00251         uint8_t s_bit : 1;
00252 #else
00253         uint8_t s_bit : 1;
00254         uint8_t res_bits : 7;
00255 #endif
00256         uint32_t orig_dest;
00257         uint32_t orig_src;         // if s_bit set
00258 } ip_mime_opt_static_t;
00259 
00260 /**
00261  * @brief Define the IPv6 Authentication option header.
00262  *
00263  */
00264 
00265 typedef struct __attribute__((packed)) ip_ah_opt
00266 {
00267         uint8_t next_header;
00268         uint8_t length;
00269         uint16_t res_bits;
00270         uint32_t spi;
00271         uint32_t sequence_number;
00272         uint32_t auth_data[1];
00273 } ip_ah_opt_t;
00274 
00275 /**
00276  * @brief Define the static part of IPv6 Authentication option header.
00277  *
00278  */
00279 
00280 typedef struct __attribute__((packed)) ip_ah_opt_static
00281 {
00282         uint8_t next_header;
00283         uint8_t length;
00284         uint32_t spi;
00285 } ip_ah_opt_static_t;
00286 
00287 /**
00288  * @brief Define the dynamic part of IPv6 Authentication option header.
00289  *
00290  */
00291 
00292 typedef struct __attribute__((packed)) ip_ah_opt_dynamic
00293 {
00294         uint32_t sequence_number;
00295         uint32_t auth_data[0];
00296 } ip_ah_opt_dynamic_t;
00297 
00298 /**
00299  * @brief Define the common IP v4/v6 header.
00300  *
00301  */
00302 
00303 typedef struct __attribute__((packed)) base_header_ip_vx
00304 {
00305 #if WORDS_BIGENDIAN != 1
00306         uint8_t reserved : 4;
00307         uint8_t version : 4;
00308 #else
00309         uint8_t version : 4;
00310         uint8_t reserved : 4;
00311 #endif
00312 } base_header_ip_vx_t;
00313 
00314 /**
00315  * @brief Define the IPv4 header.
00316  *
00317  * See RFC4996 page 77
00318  */
00319 
00320 typedef struct __attribute__((packed)) base_header_ip_v4
00321 {
00322 #if WORDS_BIGENDIAN != 1
00323         uint8_t header_length : 4;
00324         uint8_t version : 4;
00325         uint8_t ip_ecn_flags : 2;
00326         uint8_t dscp : 6;
00327 #else
00328         uint8_t version : 4;
00329         uint8_t header_length : 4;
00330         uint8_t dscp : 6;
00331         uint8_t ip_ecn_flags : 2;
00332 #endif
00333         uint16_t length;
00334         uint16_t ip_id;
00335 #if WORDS_BIGENDIAN != 1
00336         uint8_t frag_offset1 : 5;
00337         uint8_t mf : 1;
00338         uint8_t df : 1;
00339         uint8_t rf : 1;
00340         uint8_t frag_offset2;
00341 #else
00342         uint16_t rf : 1;
00343         uint16_t df : 1;
00344         uint16_t mf : 1;
00345         uint16_t frag_offset : 13;
00346 #endif
00347         uint8_t ttl_hopl;
00348         uint8_t protocol;
00349         uint16_t checksum;
00350         uint32_t src_addr;
00351         uint32_t dest_addr;
00352         // extension_headers
00353 } base_header_ip_v4_t;
00354 
00355 /**
00356  * @brief Define the IP v6 header.
00357  *
00358  * See RFC4996 page 78
00359  */
00360 
00361 typedef struct __attribute__((packed)) base_header_ip_v6
00362 {
00363 #if WORDS_BIGENDIAN != 1
00364         uint8_t dscp1 : 4;
00365         uint8_t version : 4;
00366         uint8_t flow_label1 : 4;
00367         uint8_t ip_ecn_flags : 2;
00368         uint8_t dscp2 : 2;
00369 #else
00370         uint16_t version : 4;
00371         uint16_t dscp1:4;
00372         uint16_t dscp2:2;
00373         uint16_t ip_ecn_flags : 2;
00374         uint16_t flow_label1 : 4;
00375 #endif
00376         uint16_t flow_label2;
00377         uint16_t payload_length;
00378         uint8_t next_header;
00379         uint8_t ttl_hopl;
00380         uint32_t src_addr[4];
00381         uint32_t dest_addr[4];
00382         // extension_headers
00383 } base_header_ip_v6_t;
00384 
00385 #define DSCP_V6(ptr)       (((ptr)->dscp1 << 2) | (ptr)->dscp2)
00386 #define FLOW_LABEL_V6(ptr) (((ptr->flow_label1) << 16) | ptr->flow_label2)
00387 
00388 /**
00389  * @brief Define the IP v4 static part.
00390  *
00391  * See RFC4996 page 62
00392  */
00393 
00394 typedef struct __attribute__((packed)) ipv4_static
00395 {
00396 #if WORDS_BIGENDIAN != 1
00397         uint8_t reserved : 7;
00398         uint8_t version_flag : 1;
00399 #else
00400         uint8_t version_flag : 1;
00401         uint8_t reserved : 7;
00402 #endif
00403         uint8_t protocol;
00404         uint32_t src_addr;
00405         uint32_t dst_addr;
00406 } ipv4_static_t;
00407 
00408 
00409 /** The different IP-ID behaviors */
00410 typedef enum
00411 {
00412         IP_ID_BEHAVIOR_SEQ       = 0, /**< IP-ID increases */
00413         IP_ID_BEHAVIOR_SEQ_SWAP  = 1, /**< IP-ID increases in little endian */
00414         IP_ID_BEHAVIOR_RAND      = 2, /**< IP-ID is random */
00415         IP_ID_BEHAVIOR_ZERO      = 3, /**< IP-ID is constant zero */
00416 } tcp_ip_id_behavior_t;
00417 
00418 
00419 /**
00420  * @brief Define the IP v4 dynamic part without ip_id.
00421  *
00422  * See RFC4996 page 62
00423  */
00424 
00425 typedef struct __attribute__((packed)) ipv4_dynamic1
00426 {
00427 #if WORDS_BIGENDIAN != 1
00428         uint8_t ip_id_behavior : 2;
00429         uint8_t df : 1;
00430         uint8_t reserved : 5;
00431         uint8_t ip_ecn_flags : 2;
00432         uint8_t dscp : 6;
00433 #else
00434         uint8_t reserved : 5;
00435         uint8_t df : 1;
00436         uint8_t ip_id_behavior : 2;
00437         uint8_t dscp : 6;
00438         uint8_t ip_ecn_flags : 2;
00439 #endif
00440         uint8_t ttl_hopl;
00441 } ipv4_dynamic1_t;
00442 
00443 /**
00444  * @brief Define the IP v4 dynamic part with ip_id field.
00445  *
00446  * See RFC4996 page 62
00447  */
00448 
00449 typedef struct __attribute__((packed)) ipv4_dynamic2
00450 {
00451 #if WORDS_BIGENDIAN != 1
00452         uint8_t ip_id_behavior : 2;
00453         uint8_t df : 1;
00454         uint8_t reserved : 5;
00455         uint8_t ip_ecn_flags : 2;
00456         uint8_t dscp : 6;
00457 #else
00458         uint8_t reserved : 5;
00459         uint8_t df : 1;
00460         uint8_t ip_id_behavior : 2;
00461         uint8_t dscp : 6;
00462         uint8_t ip_ecn_flags : 2;
00463 #endif
00464         uint8_t ttl_hopl;
00465         uint16_t ip_id;
00466 } ipv4_dynamic2_t;
00467 
00468 /**
00469  * @brief Define the IP v4 replicate part.
00470  *
00471  * See RFC4996 page 63
00472  */
00473 
00474 typedef struct __attribute__((packed)) ipv4_replicate
00475 {
00476 #if WORDS_BIGENDIAN != 1
00477         uint8_t df : 1;
00478         uint8_t ttl_flag : 1;
00479         uint8_t ip_id_behavior : 2;
00480         uint8_t reserved : 4;
00481         uint8_t ip_ecn_flags : 2;
00482         uint8_t dscp : 6;
00483 #else
00484         uint8_t reserved : 4;
00485         uint8_t ip_id_behavior : 2;
00486         uint8_t ttl_flag : 1;
00487         uint8_t df : 1;
00488         uint8_t dscp : 6;
00489         uint8_t ip_ecn_flags : 2;
00490 #endif
00491 //  uint16_t    ip_id;
00492 //  uint8_t     ttl_hopl;
00493 } ipv4_replicate_t;
00494 
00495 /**
00496  * @brief Define the IP v6 static part, null flow_label encoded with 1 bit
00497  *
00498  * See RFC4996 page 58
00499  */
00500 
00501 typedef struct __attribute__((packed)) ipv6_static1
00502 {
00503 #if WORDS_BIGENDIAN != 1
00504         uint8_t reserved2 : 4;
00505         uint8_t flow_label_enc_discriminator : 1;
00506         uint8_t reserved1 : 2;
00507         uint8_t version_flag : 1;
00508 #else
00509         uint8_t version_flag : 1;
00510         uint8_t reserved1 : 2;
00511         uint8_t flow_label_enc_discriminator : 1;
00512         uint8_t reserved2 : 4;
00513 #endif
00514         uint8_t next_header;
00515         uint32_t src_addr[4];
00516         uint32_t dst_addr[4];
00517 } ipv6_static1_t;
00518 
00519 /**
00520  * @brief Define the IP v6 static part, flow_label encoded with 1+20 bits
00521  *
00522  * See RFC4996 page 59
00523  */
00524 
00525 typedef struct __attribute__((packed)) ipv6_static2
00526 {
00527 #if WORDS_BIGENDIAN != 1
00528         uint8_t flow_label1 : 4;
00529         uint8_t flow_label_enc_discriminator : 1;
00530         uint8_t reserved : 2;
00531         uint8_t version_flag : 1;
00532 #else
00533         uint8_t version_flag : 1;
00534         uint8_t reserved : 2;
00535         uint8_t flow_label_enc_discriminator : 1;
00536         uint8_t flow_label1 : 4;
00537 #endif
00538         uint16_t flow_label2;
00539         uint8_t next_header;
00540         uint32_t src_addr[4];
00541         uint32_t dst_addr[4];
00542 } ipv6_static2_t;
00543 
00544 /**
00545  * @brief Define the IP v6 dynamic part.
00546  *
00547  * See RFC4996 page 59
00548  */
00549 
00550 typedef struct __attribute__((packed)) ipv6_dynamic
00551 {
00552 #if WORDS_BIGENDIAN != 1
00553         uint8_t ip_ecn_flags : 2;
00554         uint8_t dscp : 6;
00555 #else
00556         uint8_t dscp : 6;
00557         uint8_t ip_ecn_flags : 2;
00558 #endif
00559         uint8_t ttl_hopl;
00560 } ipv6_dynamic_t;
00561 
00562 /**
00563  * @brief Define the IP v6 replicate part, flow_label encoded with 5 bits
00564  *
00565  * See RFC4996 page 59
00566  */
00567 
00568 typedef struct __attribute__((packed)) ipv6_replicate1
00569 {
00570 #if WORDS_BIGENDIAN != 1
00571         uint8_t ip_ecn_flags : 2;
00572         uint8_t dscp : 6;
00573         uint8_t flow_label : 5;
00574         uint8_t reserved : 3;
00575 #else
00576         uint8_t dscp : 6;
00577         uint8_t ip_ecn_flags : 2;
00578         uint8_t reserved : 3;
00579         uint8_t flow_label : 5;
00580 #endif
00581 } ipv6_replicate1_t;
00582 
00583 /**
00584  * @brief Define the IP v6 replicate part, flow_label encoded with 21 bits
00585  *
00586  * See RFC4996 page 59
00587  */
00588 
00589 typedef struct __attribute__((packed)) ipv6_replicate2
00590 {
00591 #if WORDS_BIGENDIAN != 1
00592         uint8_t ip_ecn_flags : 2;
00593         uint8_t dscp : 6;
00594         uint8_t flow_label1 : 5;
00595         uint8_t reserved : 3;
00596 #else
00597         uint8_t dscp : 6;
00598         uint8_t ip_ecn_flags : 2;
00599         uint8_t reserved : 3;
00600         uint8_t flow_label1 : 5;
00601 #endif
00602         uint16_t flow_label2;
00603 } ipv6_replicate2_t;
00604 
00605 /**
00606  * @brief Define the IP v6 extension
00607  *
00608  */
00609 
00610 /* The high-order 3 bits of the option type define the behavior
00611  * when processing an unknown option and whether or not the option
00612  * content changes in flight.
00613  */
00614 
00615 typedef struct  __attribute__((packed)) ipv6_extension
00616 {
00617         uint8_t next_header;
00618         uint8_t extension_length;
00619         uint8_t datas[1];
00620 } ipv6_extension_t;
00621 
00622 /**
00623  * @brief Define the Selective Acknowlegment TCP option
00624  *
00625  * See RFC2018 for TCP Selective Acknowledgement Options
00626  * See RFC4996 page 66
00627  */
00628 
00629 typedef struct __attribute__((packed))
00630 {
00631         uint32_t block_start;
00632         uint32_t block_end;
00633 } sack_block_t;
00634 
00635 /**
00636  * @brief Define the TCP header
00637  *
00638  * See RFC4996 page 72/73
00639  */
00640 
00641 typedef struct __attribute__((packed)) tcphdr
00642 {
00643         uint16_t src_port;
00644         uint16_t dst_port;
00645         uint32_t seq_num;
00646         uint32_t ack_num;
00647 #if WORDS_BIGENDIAN != 1
00648         uint8_t res_flags : 4;
00649         uint8_t data_offset : 4;
00650         uint8_t rsf_flags : 3;
00651         uint8_t psh_flag : 1;
00652         uint8_t ack_flag : 1;
00653         uint8_t urg_flag : 1;
00654         uint8_t ecn_flags : 2;
00655 #else
00656         uint8_t data_offset : 4;
00657         uint8_t res_flags : 4;
00658         uint8_t ecn_flags : 2;
00659         uint8_t urg_flag : 1;
00660         uint8_t ack_flag : 1;
00661         uint8_t psh_flag : 1;
00662         uint8_t rsf_flags : 3;
00663 #endif
00664         uint16_t window;
00665         uint16_t checksum;
00666         uint16_t urg_ptr;
00667         uint8_t options[0];          /**< The beginning of the TCP options */
00668 } tcphdr_t;
00669 
00670 
00671 /** The largest index that may be used to identify one TCP option */
00672 #define MAX_TCP_OPTION_INDEX 15U
00673 
00674 /**
00675  * @brief The maximum of TCP options
00676  *
00677  * One TCP header may contain up to 40 bytes of options, so it may contain
00678  * up 40 1-byte options, so the ROHC (de)compressors should expect such TCP
00679  * packets. However the m field in the compressed list of TCP options (see
00680  * RFC 6846, section 6.3.3 for more details) cannot be larger than 15, so
00681  * restrict the number of TCP options that value. One TCP packet with more
00682  * than 15 TCP options will be compressed with the IP-only profile.
00683  * */
00684 #define ROHC_TCP_OPTS_MAX  15U
00685 
00686 
00687 /** The Timestamp option of the TCP header */
00688 struct tcp_option_timestamp
00689 {
00690         uint32_t ts;        /**< The timestamp value */
00691         uint32_t ts_reply;  /**< The timestamp echo reply value */
00692 } __attribute__((packed));
00693 
00694 
00695 /**
00696  * @brief Define the RSF flags
00697  *
00698  */
00699 
00700 #define RSF_RST_ONLY  0x04
00701 #define RSF_SYN_ONLY  0x02
00702 #define RSF_FIN_ONLY  0x01
00703 #define RSF_NONE      0x00
00704 
00705 /**
00706  * @brief Define the TCP static part.
00707  *
00708  * See RFC4996 page 73/74
00709  */
00710 
00711 typedef struct __attribute__((packed)) tcp_static
00712 {
00713         uint16_t src_port;               // =:= irregular(16)                               [ 16 ];
00714         uint16_t dst_port;               // =:= irregular(16)                               [ 16 ];
00715 } tcp_static_t;
00716 
00717 /**
00718  * @brief Define the TCP dynamic part.
00719  *
00720  * See RFC4996 page 73/74
00721  */
00722 
00723 typedef struct __attribute__((packed)) tcp_dynamic
00724 {
00725 #if WORDS_BIGENDIAN != 1
00726         uint8_t tcp_res_flags : 4;     // =:= irregular(4)                                [ 4 ];
00727         uint8_t urp_zero : 1;          // =:= irregular(1)                                [ 1 ];
00728         uint8_t ack_zero : 1;          // =:= irregular(1)                                [ 1 ];
00729         uint8_t ack_stride_flag : 1;   // =:= irregular(1)                                [ 1 ];
00730         uint8_t ecn_used : 1;          // =:= one_bit_choice                              [ 1 ];
00731 
00732         uint8_t rsf_flags : 3;         // =:= irregular(3)                                [ 3 ];
00733         uint8_t psh_flag : 1;          // =:= irregular(1)                                [ 1 ];
00734         uint8_t ack_flag : 1;          // =:= irregular(1)                                [ 1 ];
00735         uint8_t urg_flag : 1;          // =:= irregular(1)                                [ 1 ];
00736         uint8_t tcp_ecn_flags : 2;     // =:= irregular(2)                                [ 2 ];
00737 
00738 #else
00739 
00740         uint8_t ecn_used : 1;          // =:= one_bit_choice                              [ 1 ];
00741         uint8_t ack_stride_flag : 1;   // =:= irregular(1)                                [ 1 ];
00742         uint8_t ack_zero : 1;          // =:= irregular(1)                                [ 1 ];
00743         uint8_t urp_zero : 1;          // =:= irregular(1)                                [ 1 ];
00744         uint8_t tcp_res_flags : 4;     // =:= irregular(4)                                [ 4 ];
00745 
00746         uint8_t tcp_ecn_flags : 2;     // =:= irregular(2)                                [ 2 ];
00747         uint8_t urg_flag : 1;          // =:= irregular(1)                                [ 1 ];
00748         uint8_t ack_flag : 1;          // =:= irregular(1)                                [ 1 ];
00749         uint8_t psh_flag : 1;          // =:= irregular(1)                                [ 1 ];
00750         uint8_t rsf_flags : 3;         // =:= irregular(3)                                [ 3 ];
00751 
00752 #endif
00753 
00754         uint16_t msn;                 // =:= irregular(16)                               [ 16 ];
00755         uint32_t seq_num;             // =:= irregular(32)                               [ 32 ];
00756 //      uint32_t        ack_num;             // =:= zero_or_irreg(ack_zero.CVALUE, 32)          [ 0, 32 ];
00757 //      uint16_t        window;              // =:= irregular(16)                               [ 16 ];
00758 //      uint16_t        checksum;            // =:= irregular(16)                               [ 16 ];
00759 //      uint16_t        urg_ptr;             // =:= zero_or_irreg(urp_zero.CVALUE, 16)          [ 0, 16 ];
00760 //      uint16_t        ack_stride;          // =:= static_or_irreg(ack_stride_flag.CVALUE, 16) [ 0, 16 ];
00761 //      options                          // =:= list_tcp_options                            [ VARIABLE ];
00762 } tcp_dynamic_t;
00763 
00764 /**
00765  * @brief Define the TCP replicate part.
00766  *
00767  * See RFC4996 page 74/75
00768  */
00769 
00770 typedef struct __attribute__((packed)) tcp_replicate
00771 {
00772 #if WORDS_BIGENDIAN != 1
00773 
00774         uint8_t dst_port_presence : 2; // =:= irregular(2)                                [ 2 ];
00775         uint8_t src_port_presence : 2; // =:= irregular(2)                                [ 2 ];
00776         uint8_t list_present : 1;      // =:= irregular(1)                                [ 1 ];
00777         uint8_t window_presence : 1;   // =:= irregular(1)                                [ 1 ];
00778         uint8_t reserved : 1;          // =:= irregular(1)                                [ 1 ];
00779 
00780         uint8_t ecn_used : 1;          // =:= one_bit_choice                              [ 1 ];
00781         uint8_t rsf_flags : 2;         // =:= rsf_index_enc                               [ 2 ];
00782         uint8_t psh_flag : 1;          // =:= irregular(1)                                [ 1 ];
00783         uint8_t ack_flag : 1;          // =:= irregular(1)                                [ 1 ];
00784         uint8_t urg_flag : 1;          // =:= irregular(1)                                [ 1 ];
00785         uint8_t urp_presence : 1;      // =:= irregular(1)                                [ 1 ];
00786         uint8_t ack_presence : 1;      // =:= irregular(1)                                [ 1 ];
00787         uint8_t ack_stride_flag : 1;   // =:= irregular(1)                                [ 1 ];
00788 
00789 #else
00790 
00791         uint8_t reserved : 1;          // =:= irregular(1)                                [ 1 ];
00792         uint8_t window_presence : 1;   // =:= irregular(1)                                [ 1 ];
00793         uint8_t list_present : 1;      // =:= irregular(1)                                [ 1 ];
00794         uint8_t src_port_presence : 2; // =:= irregular(2)                                [ 2 ];
00795         uint8_t dst_port_presence : 2; // =:= irregular(2)                                [ 2 ];
00796 
00797         uint8_t ack_stride_flag : 1;   // =:= irregular(1)                                [ 1 ];
00798         uint8_t ack_presence : 1;      // =:= irregular(1)                                [ 1 ];
00799         uint8_t urp_presence : 1;      // =:= irregular(1)                                [ 1 ];
00800         uint8_t urg_flag : 1;          // =:= irregular(1)                                [ 1 ];
00801         uint8_t ack_flag : 1;          // =:= irregular(1)                                [ 1 ];
00802         uint8_t psh_flag : 1;          // =:= irregular(1)                                [ 1 ];
00803         uint8_t rsf_flags : 2;         // =:= rsf_index_enc                               [ 2 ];
00804         uint8_t ecn_used : 1;          // =:= one_bit_choice                              [ 1 ];
00805 
00806 #endif
00807 
00808         uint16_t msn;                 // =:= irregular(16)                               [ 16 ];
00809         uint32_t seq_num;             // =:= irregular(32)                               [ 32 ];
00810 //      uint16_t        src_port;            // =:= port_replicate(src_port_presence)           [ 0, 8, 16 ];
00811 //      uint16_t        dst_port;            // =:= port_replicate(dst_port_presence)           [ 0, 8, 16 ];
00812 //      uint16_t        window;              // =:= static_or_irreg(window_presence, 16)        [ 0, 16 ];
00813 //      uint16_t        urg_point;           // =:= static_or_irreg(urp_presence, 16)           [ 0, 16 ];
00814 //      uint32_t        ack_num;             // =:= static_or_irreg(ack_presence, 32)           [ 0, 32 ];
00815 //      uint8_t         ecn_padding:2;       // =:= optional_2bit_padding(ecn_used.CVALUE)      [ 0, 2 ];
00816 //      uint8_t         tcp_res_flags:4;     // =:= static_or_irreg(ecn_used.CVALUE, 4)         [ 0, 4 ];
00817 //      uint8_t         tcp_ecn_flags:2;     // =:= static_or_irreg(ecn_used.CVALUE, 2)         [ 0, 2 ];
00818 //      uint16_t        checksum;            // =:= irregular(16)                               [ 16 ];
00819 //      uint16_t        ack_stride;          // =:= static_or_irreg(ack_stride_flag.CVALUE, 16) [ 0, 16 ];
00820 //      options                          // =:= tcp_list_presence_enc(list_present.CVALUE)  [ VARIABLE ];
00821 
00822 } tcp_replicate_t;
00823 
00824 /**
00825  * @brief Define the TCP options.
00826  *
00827  */
00828 
00829 #define TCP_OPT_EOL               0
00830 #define TCP_OPT_NOP               1
00831 #define TCP_OPT_MAXSEG            2
00832 #define TCP_OLEN_MAXSEG           4
00833 #define TCP_OPT_WINDOW            3
00834 #define TCP_OLEN_WINDOW           3
00835 #define TCP_OPT_SACK_PERMITTED    4               /* Experimental */
00836 #define TCP_OLEN_SACK_PERMITTED   2
00837 #define TCP_OPT_SACK              5               /* Experimental */
00838 #define TCP_OPT_TIMESTAMP         8
00839 #define TCP_OLEN_TIMESTAMP        10
00840 #define TCP_OLEN_TSTAMP_APPA     (TCP_OLEN_TIMESTAMP + 2) /* appendix A */
00841 
00842 #define TCP_OPT_TSTAMP_HDR      \
00843    (TCP_OPT_NOP << 24 | TCP_OPT_NOP << 16 | TCP_OPT_TIMESTAMP << 8 | TCP_OLEN_TIMESTAMP)
00844 
00845 #define TCP_INDEX_NOP             0
00846 #define TCP_INDEX_EOL             1
00847 #define TCP_INDEX_MAXSEG          2
00848 #define TCP_INDEX_WINDOW          3
00849 #define TCP_INDEX_TIMESTAMP       4
00850 #define TCP_INDEX_SACK_PERMITTED  5
00851 #define TCP_INDEX_SACK            6
00852 
00853 /**
00854  * @brief Define the Common compressed packet format
00855  *
00856  * See RFC4996 page 80/81
00857  */
00858 
00859 typedef struct __attribute__((packed)) co_common
00860 {
00861 #if WORDS_BIGENDIAN != 1
00862 
00863         uint8_t ttl_hopl_outer_flag : 1;   // =:= compressed_value(1, ttl_irregular_chain_flag) [ 1 ];
00864         uint8_t discriminator : 7;         // =:= '1111101'
00865 
00866         uint8_t msn : 4;                   // =:= lsb(4, 4)                                     [ 4 ];
00867         uint8_t rsf_flags : 2;             // =:= rsf_index_enc                                 [ 2 ];
00868         uint8_t psh_flag : 1;              // =:= irregular(1)                                  [ 1 ];
00869         uint8_t ack_flag : 1;              // =:= irregular(1)                                  [ 1 ];
00870 
00871         uint8_t urg_ptr_present : 1;       // =:= irregular(1)                                  [ 1 ];
00872         uint8_t ip_id_indicator : 1;       // =:= irregular(1)                                  [ 1 ];
00873         uint8_t window_indicator : 1;      // =:= irregular(1)                                  [ 1 ];
00874         uint8_t ack_stride_indicator : 1;  // =:= irregular(1)                                  [ 1 ];
00875         uint8_t ack_indicator : 2;         // =:= irregular(2)                                  [ 2 ];
00876         uint8_t seq_indicator : 2;         // =:= irregular(2)                                  [ 2 ];
00877 
00878         uint8_t urg_flag : 1;              // =:= irregular(1)                                  [ 1 ];
00879         uint8_t ip_id_behavior : 2;        // =:= ip_id_behavior_choice(true)                   [ 2 ];
00880         uint8_t list_present : 1;          // =:= irregular(1)                                  [ 1 ];
00881         uint8_t ttl_hopl_present : 1;      // =:= irregular(1)                                  [ 1 ];
00882         uint8_t dscp_present : 1;          // =:= irregular(1)                                  [ 1 ];
00883         uint8_t ecn_used : 1;              // =:= one_bit_choice                                [ 1 ];
00884         uint8_t reserved : 1;              // =:= compressed_value(1, 0)                        [ 1 ];
00885 
00886         uint8_t header_crc : 7;            // =:= crc7(THIS.UVALUE,THIS.ULENGTH)                [ 7 ];
00887         uint8_t df : 1;                    // =:= dont_fragment(version.UVALUE)                 [ 1 ];
00888 
00889 #else
00890 
00891         uint8_t discriminator : 7;         // =:= '1111101'
00892         uint8_t ttl_hopl_outer_flag : 1;   // =:= compressed_value(1, ttl_irregular_chain_flag) [ 1 ];
00893 
00894         uint8_t ack_flag : 1;              // =:= irregular(1)                                  [ 1 ];
00895         uint8_t psh_flag : 1;              // =:= irregular(1)                                  [ 1 ];
00896         uint8_t rsf_flags : 2;             // =:= rsf_index_enc                                 [ 2 ];
00897         uint8_t msn : 4;                   // =:= lsb(4, 4)                                     [ 4 ];
00898 
00899         uint8_t seq_indicator : 2;         // =:= irregular(2)                                  [ 2 ];
00900         uint8_t ack_indicator : 2;         // =:= irregular(2)                                  [ 2 ];
00901         uint8_t ack_stride_indicator : 1;  // =:= irregular(1)                                  [ 1 ];
00902         uint8_t window_indicator : 1;      // =:= irregular(1)                                  [ 1 ];
00903         uint8_t ip_id_indicator : 1;       // =:= irregular(1)                                  [ 1 ];
00904         uint8_t urg_ptr_present : 1;       // =:= irregular(1)                                  [ 1 ];
00905 
00906         uint8_t reserved : 1;              // =:= compressed_value(1, 0)                        [ 1 ];
00907         uint8_t ecn_used : 1;              // =:= one_bit_choice                                [ 1 ];
00908         uint8_t dscp_present : 1;          // =:= irregular(1)                                  [ 1 ];
00909         uint8_t ttl_hopl_present : 1;      // =:= irregular(1)                                  [ 1 ];
00910         uint8_t list_present : 1;          // =:= irregular(1)                                  [ 1 ];
00911         uint8_t ip_id_behavior : 2;        // =:= ip_id_behavior_choice(true)                   [ 2 ];
00912         uint8_t urg_flag : 1;              // =:= irregular(1)                                  [ 1 ];
00913 
00914         uint8_t df : 1;                    // =:= dont_fragment(version.UVALUE)                 [ 1 ];
00915         uint8_t header_crc : 7;            // =:= crc7(THIS.UVALUE,THIS.ULENGTH)                [ 7 ];
00916 
00917 #endif
00918 
00919 //  u_intXX_t   seq_num:X;              // =:= variable_length_32_enc(seq_indicator.CVALUE)                     [ 0, 8, 16, 32 ];
00920 //  u_intXX_t   ack_num:X;              // =:= variable_length_32_enc(ack_indicator.CVALUE)                     [ 0, 8, 16, 32 ];
00921 //  u_intXX_t   ack_stride:X;           // =:= static_or_irreg(ack_stride_indicator.CVALUE, 16)                 [ 0, 16 ];
00922 //  u_intXX_t  window:X;               // =:= static_or_irreg(window_indicator.CVALUE, 16)                     [ 0, 16 ];
00923 //  u_intXX_t  ip_id:X;                // =:= optional_ip_id_lsb(ip_id_behavior.UVALUE,ip_id_indicator.CVALUE) [ 0, 8, 16 ];
00924 //  u_intXX_t  urg_ptr:X;              // =:= static_or_irreg(urg_ptr_present.CVALUE, 16)                      [ 0, 16 ];
00925 //  u_intXX_t   dscp:X;                 // =:= dscp_enc-dscp_present.CVALUE)                                    [ 0, 8 ];
00926 //  u_intXX_t   ttl_hopl:X;             // =:= static_or_irreg(ttl_hopl_present.CVALUE, 8)                      [ 0, 8 ];
00927 //  options                            // =:= tcp_list_presence_enc(list_present.CVALUE)                       [ VARIABLE ];
00928 
00929 } co_common_t;
00930 
00931 
00932 /**
00933  * @brief Define the rnd_1 compressed packet format
00934  *
00935  * Send LSBs of sequence number
00936  * See RFC4996 page 81
00937  */
00938 typedef struct __attribute__((packed)) rnd_1
00939 {
00940 #if WORDS_BIGENDIAN != 1
00941         uint8_t seq_num1:2;           // =:= lsb(18, 65535)           [ 18 ];
00942         uint8_t discriminator : 6;         // =:= '101110'                                       [ 6 ];
00943         uint16_t seq_num2;            // =:= lsb(18, 65535)           [ 18 ];
00944         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
00945         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
00946         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
00947 #else
00948         uint8_t discriminator : 6;         // =:= '101110'                                       [ 6 ];
00949         uint8_t seq_num1:2;          // =:= lsb(18, 65535)           [ 18 ];
00950         uint16_t seq_num2;           // =:= lsb(18, 65535)           [ 18 ];
00951         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
00952         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
00953         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
00954 #endif
00955 } rnd_1_t;
00956 
00957 
00958 /**
00959  * @brief Define the rnd_2 compressed packet format
00960  *
00961  * Send scaled sequence number LSBs
00962  * See RFC4996 page 81
00963  */
00964 typedef struct __attribute__((packed)) rnd_2
00965 {
00966 #if WORDS_BIGENDIAN != 1
00967         uint8_t seq_num_scaled:4;     // =:= lsb(4, 7)             [ 4 ];
00968         uint8_t discriminator : 4;         // =:= '1100'                                         [ 4 ];
00969         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
00970         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
00971         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
00972 #else
00973         uint8_t discriminator : 4;         // =:= '1100'                                         [ 4 ];
00974         uint8_t seq_num_scaled:4;    // =:= lsb(4, 7)             [ 4 ];
00975         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
00976         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
00977         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
00978 #endif
00979 } rnd_2_t;
00980 
00981 
00982 /**
00983  * @brief Define the rnd_3 compressed packet format
00984  *
00985  * Send acknowlegment number LSBs
00986  * See RFC4996 page 81
00987  */
00988 typedef struct __attribute__((packed)) rnd_3
00989 {
00990 #if WORDS_BIGENDIAN != 1
00991         uint8_t ack_num1:7;         // =:= lsb(15, 8191)               [ 15 ];
00992         uint8_t discriminator : 1;         // =:= '0'                                            [ 4 ];
00993         uint8_t ack_num2:8;         // =:= lsb(15, 8191)               [ 15 ];
00994         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
00995         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
00996         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
00997 #else
00998         uint16_t discriminator : 1;        // =:= '0'                                            [ 4 ];
00999         uint8_t ack_num1:7;        // =:= lsb(15, 8191)                [ 15 ];
01000         uint8_t ack_num2;          // =:= lsb(15, 8191)                [ 15 ];
01001         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01002         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01003         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01004 #endif
01005 } rnd_3_t;
01006 
01007 
01008 /**
01009  * @brief Define the rnd_4 compressed packet format
01010  *
01011  * Send acknowlegment number scaled
01012  * See RFC4996 page 81
01013  */
01014 typedef struct __attribute__((packed)) rnd_4
01015 {
01016 #if WORDS_BIGENDIAN != 1
01017         uint8_t ack_num_scaled:4;   // =:= lsb(4, 3)                [ 4 ];
01018         uint8_t discriminator : 4;         // =:= '1101'                                         [ 4 ];
01019 
01020         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01021         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01022         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01023 #else
01024         uint8_t discriminator : 4;         // =:= '1101'                                         [ 4 ];
01025         uint8_t ack_num_scaled:4;   // =:= lsb(4, 3)                [ 4 ];
01026 
01027         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01028         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01029         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01030 #endif
01031 } rnd_4_t;
01032 
01033 
01034 /**
01035  * @brief Define the rnd_5 compressed packet format
01036  *
01037  * Send ACK and sequence number
01038  * See RFC4996 page 82
01039  */
01040 typedef struct __attribute__((packed)) rnd_5
01041 {
01042 #if WORDS_BIGENDIAN != 1
01043         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01044         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01045         uint8_t discriminator : 3;         // =:= '100'                                          [ 3 ];
01046 
01047         uint8_t seq_num1:5;          // =:= lsb(15, 8191)           [ 15 ];
01048         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01049         uint8_t seq_num2;            // =:= lsb(15, 8191)           [ 15 ];
01050         uint8_t ack_num1:7;          // =:= lsb(15, 8191)           [ 15 ];
01051         uint8_t seq_num3:1;          // =:= lsb(15, 8191)           [ 15 ];
01052         uint8_t ack_num2;            // =:= lsb(15, 8191)           [ 15 ];
01053 #else
01054         uint8_t discriminator : 3;         // =:= '100'                                          [ 3 ];
01055         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01056         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01057 
01058         uint32_t header_crc : 3;           // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01059         uint32_t seq_num1:5;        // =:= lsb(14, 8191)            [ 14 ];
01060         uint32_t seq_num2:8;        // =:= lsb(14, 8191)            [ 14 ];
01061         uint32_t seq_num3:1;        // =:= lsb(14, 8191)            [ 14 ];
01062         uint32_t ack_num1:7;        // =:= lsb(15, 8191)            [ 15 ];
01063         uint32_t ack_num2:8;        // =:= lsb(15, 8191)            [ 15 ];
01064 #endif
01065 } rnd_5_t;
01066 
01067 
01068 /**
01069  * @brief Define the rnd_6 compressed packet format
01070  *
01071  * Send both ACK and scaled sequence number LSBs
01072  * See RFC4996 page 82
01073  */
01074 typedef struct __attribute__((packed)) rnd_6
01075 {
01076 #if WORDS_BIGENDIAN != 1
01077         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01078         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01079         uint8_t discriminator : 4;         // =:= '1010'                                         [ 4 ];
01080 #else
01081         uint8_t discriminator : 4;         // =:= '1010'                                         [ 4 ];
01082         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01083         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01084 #endif
01085         uint16_t ack_num;            // =:= lsb(16, 16383)        [ 16 ];
01086 #if WORDS_BIGENDIAN != 1
01087         uint8_t seq_num_scaled:4;    // =:= lsb(4, 7)             [ 4 ];
01088         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01089 #else
01090         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01091         uint8_t seq_num_scaled:4;    // =:= lsb(4, 7)             [ 4 ];
01092 #endif
01093 } rnd_6_t;
01094 
01095 
01096 /**
01097  * @brief Define the rnd_7 compressed packet format
01098  *
01099  * Send ACK and window
01100  * See RFC4996 page 82
01101  */
01102 typedef struct __attribute__((packed)) rnd_7
01103 {
01104 #if WORDS_BIGENDIAN != 1
01105         uint8_t ack_num1:2;         // =:= lsb(18, 65535)            [ 18 ];
01106         uint8_t discriminator : 6;         // =:= '101111'                                       [ 6 ];
01107         uint16_t ack_num2;          // =:= lsb(18, 65535)            [ 18 ];
01108 #else
01109         uint8_t discriminator : 6;         // =:= '101111'                                       [ 6 ];
01110         uint8_t ack_num1:2;         // =:= lsb(18, 65535)            [ 18 ];
01111         uint16_t ack_num2;          // =:= lsb(18, 65535)            [ 18 ];
01112 #endif
01113         uint16_t window;                   // =:= irregular(16)                                  [ 16 ];
01114 #if WORDS_BIGENDIAN != 1
01115         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01116         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01117         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01118 #else
01119         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01120         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01121         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01122 #endif
01123 } rnd_7_t;
01124 
01125 
01126 /**
01127  * @brief Define the rnd_8 compressed packet format
01128  *
01129  * Can send LSBs of TTL, RSF flags, change ECN behavior and options list
01130  * See RFC4996 page 82
01131  */
01132 typedef struct __attribute__((packed)) rnd_8
01133 {
01134 #if WORDS_BIGENDIAN != 1
01135         uint8_t list_present : 1;          // =:= irregular(1)                                   [ 1 ];
01136         uint8_t rsf_flags : 2;             // =:= rsf_index_enc                                  [ 2 ];
01137         uint8_t discriminator : 5;         // =:= '10110'                                        [ 5 ];
01138         uint8_t msn1 : 1;                  // =:= lsb(4, 4)                                      [ 4 ];
01139         uint8_t header_crc : 7;            // =:= crc7(THIS.UVALUE, THIS.ULENGTH)                [ 7 ];
01140         uint8_t ecn_used : 1;              // =:= one_bit_choice                                 [ 1 ];
01141         uint8_t ttl_hopl : 3;              // =:= lsb(3, 3)                                      [ 3 ];
01142         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01143         uint8_t msn2 : 3;                  // =:= lsb(4, 4)                                      [ 4 ];
01144 #else
01145         uint8_t discriminator : 5;         // =:= '10110'                                        [ 5 ];
01146         uint8_t rsf_flags : 2;             // =:= rsf_index_enc                                  [ 2 ];
01147         uint8_t list_present : 1;          // =:= irregular(1)                                   [ 1 ];
01148         uint16_t header_crc : 7;           // =:= crc7(THIS.UVALUE, THIS.ULENGTH)                [ 7 ];
01149         uint16_t msn1 : 1;                  // =:= lsb(4, 4)                                      [ 4 ];
01150         uint16_t msn2 : 3;                  // =:= lsb(4, 4)                                      [ 4 ];
01151         uint16_t psh_flag : 1;             // =:= irregular(1)                                   [ 1 ];
01152         uint16_t ttl_hopl : 3;             // =:= lsb(3, 3)                                      [ 3 ];
01153         uint16_t ecn_used : 1;             // =:= one_bit_choice                                 [ 1 ];
01154 #endif
01155         uint16_t seq_num;           // =:= lsb(16, 65535)             [ 16 ];
01156         uint16_t ack_num;           // =:= lsb(16, 16383)             [ 16 ];
01157         uint8_t options[0];                // =:= tcp_list_presence_enc(list_present.CVALUE)     [ VARIABLE ];
01158 } rnd_8_t;
01159 
01160 
01161 /**
01162  * @brief Define the seq_1 compressed packet format
01163  *
01164  * Send LSBs of sequence number
01165  * See RFC4996 page 83
01166  */
01167 typedef struct __attribute__((packed)) seq_1
01168 {
01169 #if WORDS_BIGENDIAN != 1
01170         uint8_t ip_id : 4;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 4, 3)         [ 4 ];
01171         uint8_t discriminator : 4;         // =:= '1010'                                         [ 4 ];
01172 #else
01173         uint8_t discriminator : 4;         // =:= '1010'                                         [ 4 ];
01174         uint8_t ip_id : 4;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 4, 3)         [ 4 ];
01175 #endif
01176         uint16_t seq_num;          // =:= lsb(16, 32767)             [ 16 ];
01177 #if WORDS_BIGENDIAN != 1
01178         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01179         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01180         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01181 #else
01182         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01183         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01184         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01185 #endif
01186 } seq_1_t;
01187 
01188 
01189 /**
01190  * @brief Define the seq_2 compressed packet format
01191  *
01192  * Send scaled sequence number LSBs
01193  * See RFC4996 page 83
01194  */
01195 typedef struct __attribute__((packed)) seq_2
01196 {
01197 #if WORDS_BIGENDIAN != 1
01198         uint8_t ip_id1 : 3;                // =:= ip_id_lsb(ip_id_behavior.UVALUE, 7, 3)        [ 3 ];
01199         uint8_t discriminator : 5;         // =:= '11010'                                        [ 5 ];
01200         uint8_t seq_num_scaled:4;   // =:= lsb(4, 7)                [ 4 ];
01201         uint8_t ip_id2 : 4;                // =:= ip_id_lsb(ip_id_behavior.UVALUE, 7, 3)        [ 4 ];
01202         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01203         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01204         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01205 #else
01206         uint16_t discriminator : 5;        // =:= '11010'                                        [ 5 ];
01207         uint16_t ip_id1 : 3;               // =:= ip_id_lsb(ip_id_behavior.UVALUE, 7, 3)         [ 7 ];
01208         uint16_t ip_id2 : 4;               // =:= ip_id_lsb(ip_id_behavior.UVALUE, 7, 3)         [ 7 ];
01209         uint16_t seq_num_scaled : 4;    // =:= lsb(4, 7)                                      [ 4 ];
01210         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01211         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01212         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01213 #endif
01214 } seq_2_t;
01215 
01216 
01217 /**
01218  * @brief Define the seq_3 compressed packet format
01219  *
01220  * Send acknowledgment number LSBs
01221  * See RFC4996 page 83
01222  */
01223 typedef struct __attribute__((packed)) seq_3
01224 {
01225 #if WORDS_BIGENDIAN != 1
01226         uint8_t ip_id : 4;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 4, 3)         [ 4 ];
01227         uint8_t discriminator : 4;         // =:= '1001'                                         [ 4 ];
01228 #else
01229         uint8_t discriminator : 4;         // =:= '1001'                                         [ 4 ];
01230         uint8_t ip_id : 4;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 4, 3)         [ 4 ];
01231 #endif
01232         uint16_t ack_num;          // =:= lsb(16, 16383)               [ 16 ];
01233 #if WORDS_BIGENDIAN != 1
01234         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01235         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01236         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01237 #else
01238         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01239         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01240         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01241 #endif
01242 } seq_3_t;
01243 
01244 
01245 /**
01246  * @brief Define the seq_4 compressed packet format
01247  *
01248  * Send scaled acknowledgment number scaled
01249  * See RFC4996 page 84
01250  */
01251 typedef struct __attribute__((packed)) seq_4
01252 {
01253 #if WORDS_BIGENDIAN != 1
01254         uint8_t ip_id : 3;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 3, 1)         [ 3 ];
01255         uint8_t ack_num_scaled:4;  // =:= lsb(4, 3)                 [ 4 ];
01256         uint8_t discriminator : 1;         // =:= '0'                                            [ 1 ];
01257         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01258         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01259         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01260 #else
01261         uint8_t discriminator : 1;         // =:= '0'                                            [ 1 ];
01262         uint8_t ack_num_scaled:4;  // =:= lsb(4, 3)                 [ 4 ];
01263         uint8_t ip_id : 3;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 3, 1)         [ 3 ];
01264         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01265         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01266         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01267 #endif
01268 } seq_4_t;
01269 
01270 
01271 /**
01272  * @brief Define the seq_5 compressed packet format
01273  *
01274  * Send ACK and sequence number
01275  * See RFC4996 page 84
01276  */
01277 typedef struct __attribute__((packed)) seq_5
01278 {
01279 #if WORDS_BIGENDIAN != 1
01280         uint8_t ip_id : 4;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 4, 3)         [ 4 ];
01281         uint8_t discriminator : 4;         // =:= '1000'                                         [ 4 ];
01282 #else
01283         uint8_t discriminator : 4;         // =:= '1000'                                         [ 4 ];
01284         uint8_t ip_id : 4;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 4, 3)         [ 4 ];
01285 #endif
01286         uint16_t ack_num;          // =:= lsb(16, 16383)              [ 16 ];
01287         uint16_t seq_num;          // =:= lsb(16, 32767)              [ 16 ];
01288 #if WORDS_BIGENDIAN != 1
01289         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01290         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01291         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01292 #else
01293         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01294         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01295         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01296 #endif
01297 } seq_5_t;
01298 
01299 
01300 /**
01301  * @brief Define the seq_6 compressed packet format
01302  *
01303  * Send both ACK and scaled sequence number LSBs
01304  * See RFC4996 page 84
01305  */
01306 typedef struct __attribute__((packed)) seq_6
01307 {
01308 #if WORDS_BIGENDIAN != 1
01309         uint8_t seq_num_scaled1:3;   // =:= lsb(4, 7)                  [ 3 ];
01310         uint8_t discriminator : 5;         // =:= '11011'                                        [ 5 ];
01311         uint8_t ip_id : 7;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 7, 3)         [ 7 ];
01312         uint8_t seq_num_scaled2:1;   // =:= lsb(4, 7)                  [ 1 ];
01313 #else
01314         uint16_t discriminator : 5;        // =:= '11011'                                        [ 5 ];
01315         uint16_t seq_num_scaled1:3;  // =:= lsb(4, 7)                  [ 4 ];
01316         uint16_t seq_num_scaled2:1;  // =:= lsb(4, 7)                  [ 4 ];
01317         uint16_t ip_id : 7;                // =:= ip_id_lsb(ip_id_behavior.UVALUE, 7, 3)         [ 7 ];
01318 #endif
01319         uint16_t ack_num;            // =:= lsb(16, 16383)             [ 16 ];
01320 #if WORDS_BIGENDIAN != 1
01321         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01322         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01323         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01324 #else
01325         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01326         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01327         uint8_t header_crc : 3;            // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01328 #endif
01329 } seq_6_t;
01330 
01331 
01332 /**
01333  * @brief Define the seq_7 compressed packet format
01334  *
01335  * Send ACK and window
01336  * See RFC4996 page 85
01337  */
01338 typedef struct __attribute__((packed)) seq_7
01339 {
01340 #if WORDS_BIGENDIAN != 1
01341         uint8_t window1 : 4;      // =:= lsb(15, 16383)                                 [ 15 ];
01342         uint8_t discriminator : 4;   // =:= '1100'                                         [ 4 ];
01343 
01344         uint8_t window2;
01345 
01346         uint8_t ip_id : 5;     // =:= ip_id_lsb(ip_id_behavior.UVALUE, 5, 3)         [ 5 ];
01347         uint8_t window3 : 3;
01348 
01349         uint16_t ack_num;      // =:= lsb(16, 32767)                [ 16 ];
01350 
01351         uint8_t header_crc : 3;      // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01352         uint8_t psh_flag : 1;     // =:= irregular(1)                                   [ 1 ];
01353         uint8_t msn : 4;          // =:= lsb(4, 4)                                      [ 4 ];
01354 #else
01355         uint8_t discriminator : 4;   // =:= '1100'                                         [ 4 ];
01356         uint8_t window1 : 4;      // =:= lsb(15, 16383)                                 [ 15 ];
01357 
01358         uint8_t window2;
01359 
01360         uint8_t window3 : 3;
01361         uint8_t ip_id : 5;     // =:= ip_id_lsb(ip_id_behavior.UVALUE, 5, 3)         [ 5 ];
01362 
01363         uint16_t ack_num;      // =:= lsb(16, 32767)                [ 16 ];
01364 
01365         uint8_t msn : 4;          // =:= lsb(4, 4)                                      [ 4 ];
01366         uint8_t psh_flag : 1;     // =:= irregular(1)                                   [ 1 ];
01367         uint8_t header_crc : 3;      // =:= crc3(THIS.UVALUE, THIS.ULENGTH)                [ 3 ];
01368 #endif
01369 } seq_7_t;
01370 
01371 
01372 /**
01373  * @brief Define the seq_8 compressed packet format
01374  *
01375  * Can send LSBs of TTL, RSF flags, change ECN behavior, and options list
01376  * See RFC4996 page 85
01377  */
01378 typedef struct __attribute__((packed)) seq_8
01379 {
01380 #if WORDS_BIGENDIAN != 1
01381         uint8_t ip_id : 4;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 4, 3)         [ 4 ];
01382         uint8_t discriminator : 4;         // =:= '1011'                                         [ 4 ];
01383         uint8_t header_crc : 7;            // =:= crc7(THIS.UVALUE, THIS.ULENGTH)                [ 7 ];
01384         uint8_t list_present : 1;          // =:= irregular(1)                                   [ 1 ];
01385         uint8_t ttl_hopl : 3;              // =:= lsb(3, 3)                                      [ 3 ];
01386         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01387         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01388         uint8_t ack_num1:7;       // =:= lsb(15, 8191)               [ 15 ];
01389         uint8_t ecn_used : 1;              // =:= one_bit_choice                                 [ 1 ];
01390         uint8_t ack_num2;         // =:= lsb(15, 8191)               [ 15 ];
01391         uint8_t seq_num1:6;       // =:= lsb(14, 8191)               [ 14 ];
01392         uint8_t rsf_flags : 2;             // =:= rsf_index_enc                                  [ 2 ];
01393         uint8_t seq_num2:8;       // =:= lsb(14, 8191)               [ 14 ];
01394 #else
01395         uint8_t discriminator : 4;         // =:= '1011'                                         [ 4 ];
01396         uint8_t ip_id : 4;                 // =:= ip_id_lsb(ip_id_behavior.UVALUE, 4, 3)         [ 4 ];
01397         uint8_t list_present : 1;          // =:= irregular(1)                                   [ 1 ];
01398         uint8_t header_crc : 7;            // =:= crc7(THIS.UVALUE, THIS.ULENGTH)                [ 7 ];
01399         uint8_t msn : 4;                   // =:= lsb(4, 4)                                      [ 4 ];
01400         uint8_t psh_flag : 1;              // =:= irregular(1)                                   [ 1 ];
01401         uint8_t ttl_hopl : 3;              // =:= lsb(3, 3)                                      [ 3 ];
01402         uint8_t ecn_used : 1;              // =:= one_bit_choice                                 [ 1 ];
01403         uint8_t ack_num1:7;      // =:= lsb(15, 8191)                [ 15 ];
01404         uint8_t ack_num2;        // =:= lsb(15, 8191)                [ 15 ];
01405         uint8_t rsf_flags : 2;             // =:= rsf_index_enc                                  [ 2 ];
01406         uint8_t seq_num1 : 6;    // =:= lsb(14, 8191)                [ 14 ];
01407         uint8_t seq_num2;        // =:= lsb(14, 8191)                [ 14 ];
01408 #endif
01409         uint8_t options[0];                // =:= tcp_list_presence_enc(list_present.CVALUE)     [ VARIABLE ];
01410 } seq_8_t;
01411 
01412 
01413 /**
01414  * @brief Define union of different header pointers
01415  */
01416 typedef union
01417 {
01418         unsigned int uint;
01419         uint8_t *uint8;
01420         uint16_t *uint16;
01421         base_header_ip_vx_t *ipvx;
01422         base_header_ip_v4_t *ipv4;
01423         base_header_ip_v6_t *ipv6;
01424         ipv6_opt_t *ipv6_opt;
01425         ip_dest_opt_t *ip_dest_opt;
01426         ip_hop_opt_t *ip_hop_opt;
01427         ip_rout_opt_t *ip_rout_opt;
01428         ip_gre_opt_t *ip_gre_opt;
01429         ip_mime_opt_t *ip_mime_opt;
01430         ip_ah_opt_t *ip_ah_opt;
01431         tcphdr_t *tcphdr;
01432 } base_header_ip_t;
01433 
01434 
01435 #endif /* ROHC_PROTOCOLS_TCP_H */
01436