Files
2026-07-30 11:19:44 +05:30

2641 lines
82 KiB
C

/* iprohc_tcp_ip.h - ROHC TCP/IP profile head file */
/*
* Copyright (c) 2013 Wind River Systems, Inc.
*
* The right to copy, distribute or otherwise make use of this software
* may be licensed only pursuant to the terms of an applicable Wind River
* license agreement. No license to Wind River intellectual property rights
* is granted herein. All rights not licensed by Wind River are reserved
* by Wind River.
*/
/*
modification history
--------------------
01i,08aug13,j_y Clean low impact code review defects
01h,30jul13,j_y Clean medium impact code review defects
01d,31jan13,ggz Fixed defect WIND00402004
01c,16oct12,ggz Fix warnings. Defect WIND00382425
01b,01oct11,ggz Added capability to simulate various ipid change pattern
01a,01dec09,ggz Created
*/
#ifndef IPROHC_TCP_IP_H
#define IPROHC_TCP_IP_H
/*
****************************************************************************
* INCLUDE FILES
****************************************************************************
*/
#include <ipcom_tags.h>
#include <ipcom_type.h>
#include <ipcom_list.h>
#include "iprohc_config.h"
#include "iprohc_constant.h"
#include "iprohc_ip.h"
#include "iprohc_coding_util.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* DEFINES
****************************************************************************
*/
#define IPROHC_ENABLE_REENTRANT
#define GEN_LEN 9
#define ROHC_TCP_NUM_OF_IR_PKT 5 /* IR and IR-DYN packets */
#define ROHC_TCP_PKT_IR_CR 252 /* 11111100 */
/* TCP Item Table Mappings.
* 6.3.4, RFC 4996
* +-----------------+---------------+------+
* | Option name | Table index | Kind |
* +-----------------+---------------+------+
* | NOP | 0 | 1 |
* | EOL | 1 | 0 |
* | MSS | 2 | 2 |
* | WINDOW SCALE | 3 | 3 |
* | TIMESTAMP | 4 | 8 |
* | SACK-PERMITTED | 5 | 4 |
* | SACK | 6 | 5 |
* | Generic options | 7-15 | |
* +-----------------+---------------+------+
*/
/* Item index maping table. Reserved options */
Ip_u8 item_index[9] = {1,0,2,3,5,6,255,255,4};
/* Generic options*/
Ip_u8 item_gen_index[GEN_LEN] = {7,8,9,10,11,12,13,14,15};
#define ECN_USED 0x80 /*10000000*/
/* #define ACK_STRIDE_IRREG 0x40 */ /*01000000*/
#define ACK_ZERO 0x20 /*00100000*/
#define URP_ZERO 0x10 /*00010000*/
#define LIST_PRESENT 0x8 /*00001000*/
/* General packet type masks */
#define ROHC_TCP_PKT_CO_M 0x1
#define ROHC_TCP_PKT_RND_1_M 0x2
#define ROHC_TCP_PKT_RND_2_M 0x4
#define ROHC_TCP_PKT_RND_3_M 0x7
#define ROHC_TCP_PKT_RND_4_M 0x4
#define ROHC_TCP_PKT_RND_5_M 0x5
#define ROHC_TCP_PKT_RND_6_M 0x4
#define ROHC_TCP_PKT_RND_7_M 0x2
#define ROHC_TCP_PKT_RND_8_M 0x3
#define ROHC_TCP_PKT_SEQ_1_M 0x4
#define ROHC_TCP_PKT_SEQ_2_M 0x3
#define ROHC_TCP_PKT_SEQ_3_M 0x4
#define ROHC_TCP_PKT_SEQ_4_M 0x7
#define ROHC_TCP_PKT_SEQ_5_M 0x4
#define ROHC_TCP_PKT_SEQ_6_M 0x3
#define ROHC_TCP_PKT_SEQ_7_M 0x4
#define ROHC_TCP_PKT_SEQ_8_M 0x4
/*
* TCP control flags
* tcp_ecn_flags [ 2 ];
* urg_flag [ 1 ];
* ack_flag [ 1 ];
* psh_flag [ 1 ];
* rsf_flags [ 3 ];
*/
#define ROHC_TCP_ECN_FLAGS 0xC0
#define ROHC_TCP_URG_FLAG 0x20
#define ROHC_TCP_ACK_FLAG 0x10
#define ROHC_TCP_PSH_FLAG 0x08
#define ROHC_TCP_RSF_FLAGS 0x07
/* IP ID behavior */
#define IP_ID_BEHAVIOR_SEQUENTIAL 0
#define IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED 1
#define IP_ID_BEHAVIOR_RANDOM 2
#define IP_ID_BEHAVIOR_ZERO 3
/* TCP header flags
*
* urg_ptr_irreg;
* window_irreg;
* ack_stride_irreg;
* ackn_not_present;
* sn_not_present;
*/
#define URG_PTR_IRREG 0x01
#define WINDOW_IRREG 0x02
#define ACK_STRIDE_IRREG 0x04
#define ACK_NOT_PRESENT 0x08
#define SN_NOT_PRESENT 0x10
#define TCP_RES_FLAGS_IRREG 0x20
#define TCP_ECN_FLAGS_IRREG 0x40
/* IP flags
* Outer IP header
* outer_dscp_irreg;
* outer_ip_ecn_flags_irreg;
* ttl_irregular_chain_flag;
*/
#define OUTER_DSCP_IRREG 0x01
#define OUTER_IP_ECN_FLAGS_IRREG 0x02
#define TTL_IRREGULAR_CHAIN_FLAG 0x04
/*
* Inner IP header
* dscp_irreg;
* ttl_hlim_irreg;
* ecn_present;
*/
#define DF_IRREG 0x10
#define DSCP_IRREG 0x20
#define TTL_HLIM_IRREG 0x40
#define ECN_PRESENT 0x80
/*
*===========================================================================
* IPROHC_TCP_INIT_CONTEXT
*===========================================================================
* Set the TCP context
*/
#define IPROHC_TCP_INIT_CONTEXT(tcp_context, tcp_header, pkt) \
{ \
int offset_; \
\
ipcom_memcpy(&tcp_context->src_port, &tcp_header.src_port, 20); \
\
/* Get and save mapped TCP options in the context */ \
IPROHC_TCP_INIT_OPT_LIST(tcp_context, pkt); \
\
tcp_context->c_flags = 0; \
if(tcp_context->ackn == 0) \
tcp_context->c_flags = tcp_context->c_flags | ACK_ZERO; \
if(tcp_context->uptr == 0) \
tcp_context->c_flags = tcp_context->c_flags | URP_ZERO; \
\
/* Set the TCP payload length */ \
offset_ = ((pkt->data[pkt->tlstart + 12]) >> 4) * 4; \
tcp_context->payload_ln = pkt->end - (pkt->tlstart + offset_); \
/* Set the TCP payload */ \
tcp_context->payload = pkt->tlstart + offset_; \
\
}
/*
*===========================================================================
* IPROHC_TCP_INIT_OPT_LIST
*===========================================================================
* Populate TCP options item list
*
* Sets
*/
#define IPROHC_TCP_INIT_OPT_LIST(tcp_context, pkt) \
{ \
tcp_item_list *item_list = IP_NULL; \
int item_ptr = 0, i; \
int opt_start, opt_end; \
Ip_u8 offset, item_kind = 0; \
Ip_u8 item_ln = 0; \
Ip_u8 opt_fl = 0; \
Ip_bool index_gen; \
\
offset = (Ip_u8)(tcp_context->offset_res >> 4); \
opt_start = pkt->tlstart + 20; \
opt_end = pkt->tlstart + (offset * 4); \
\
for(item_ptr = opt_start; item_ptr < opt_end;) \
{ \
item_list = ipcom_malloc(sizeof(tcp_item_list)); \
if (item_list == IP_NULL) goto err2; \
ipcom_memset(item_list, 0, sizeof(tcp_item_list)); \
opt_fl = 0; \
\
item_kind = pkt->data[item_ptr]; \
\
if(item_kind == 0) /* EOL */ \
{ \
/* EOL length is 1 byte. There can be padding after the EOL */ \
item_list->index = item_index[item_kind]; \
tcp_context->pad_ln = (Ip_u8)(opt_end - item_ptr - 1); \
item_list->item_ln = 1; \
item_ln = (Ip_u8)(tcp_context->pad_ln + 1); \
/* Dont save padding. tcp_context-pad_ln indicates the length \
of the p[adding */ \
item_list->item = ipcom_malloc(1); \
if (item_list->item == IP_NULL) goto err; \
item_list->item[0] = item_kind; \
opt_fl = 1; \
} \
else if(item_kind == 1) /* NOP */ \
{ \
item_list->index = item_index[item_kind]; \
item_list->item_ln = item_ln = 1; \
item_list->item = ipcom_malloc(1); \
if (item_list->item == IP_NULL) goto err; \
item_list->item[0] = item_kind; \
/* ipcom_memcpy(item_list->item, &item_kind, 1);*/ \
opt_fl = 1; \
} \
else \
{ \
if(((item_kind >= 2) && (item_kind <= 5)) || item_kind == 8) \
item_list->index = item_index[item_kind]; \
else \
{ \
/* Allocate gneric index */ \
index_gen = IP_FALSE; \
for(i = 0; i < GEN_LEN; i++) \
{ \
if(tcp_context->item_gen_uindex[i] == 0) \
{ \
item_list->index = item_gen_index[i]; \
tcp_context->item_gen_uindex[i] = 1; /* Mark as USED */ \
index_gen = IP_TRUE; \
break; \
} \
} \
if (index_gen == IP_FALSE) \
{ \
IPCOM_LOG0(ERR,"IPROHC_TCP_INIT_OPT_LIST, No generic index is available"); \
goto err; \
} \
} \
item_list->item_ln = item_ln = pkt->data[item_ptr + 1]; \
item_list->item = ipcom_malloc(item_ln); \
if(item_list->item == IP_NULL) goto err; \
ipcom_memcpy(item_list->item, &pkt->data[item_ptr], item_ln); \
opt_fl = 1; \
} \
\
if(item_list->index > tcp_context->max_indx) tcp_context->max_indx = item_list->index; \
ipcom_list_insert_last(&tcp_context->opt, &item_list->item_list); \
tcp_context->opt_num++; \
item_ptr = item_ptr + item_ln; \
\
} \
\
if((opt_fl == 0) && (opt_start != opt_end)) \
{ \
err: if (item_list != IP_NULL) \
{ \
if (item_list->item != IP_NULL) ipcom_free(item_list->item); \
ipcom_free(item_list); \
} \
err2: goto err1; \
} \
}
/*
*===========================================================================
* IPROHC_TCP_UPD_OPT_LIST
*===========================================================================
* Get TCP option list from the packet
*/
#define IPROHC_TCP_UPD_OPT_LIST(tcp_context, pkt) \
{ \
IPROHC_TCP_INIT_OPT_LIST(tcp_context, pkt) \
}
/*
*===========================================================================
* IPROHC_FMT_TCP_DYNAMIC
*===========================================================================
* Fomat dynamic chain in a IR/IR-DYN packet
*
*/
#define IPROHC_FMT_TCP_DYNAMC(tcp_context, pointer, pkt) \
{ \
Ip_u8 ldata; \
Ip_u16 ldata1; \
\
IPROHC_FMT_LIST_TCP_OPT(tcp_context, pkt, pointer); \
\
if (tcp_context->tcp_flags & ACK_STRIDE_IRREG) \
{ \
pointer -= 2; \
ldata1 = ipcom_htons(tcp_context->ackn_stride); \
ipcom_memcpy(&pkt->data[pointer], &ldata1, 2); \
} \
\
if (!(tcp_context->c_flags & URP_ZERO)) \
{ \
pointer -= 2; \
ipcom_memcpy(&pkt->data[pointer], &tcp_context->uptr, 2); \
} \
\
/* Checksum */ \
pointer -= 2; \
ipcom_memcpy(&pkt->data[pointer], &tcp_context->chksum, 2); \
/* Window */ \
pointer -= 2; \
ipcom_memcpy(&pkt->data[pointer], &tcp_context->window, 2); \
/* Ack number */ \
if (!(tcp_context->c_flags & ACK_ZERO)) \
{ \
pointer -= 4; \
ipcom_memcpy(&pkt->data[pointer], &tcp_context->ackn, 4); \
} \
/* Seq number */ \
pointer -= 4; \
ipcom_memcpy(&pkt->data[pointer], &tcp_context->sn, 4); \
/* MSN */ \
pointer -= 2; \
ldata1 = ipcom_htons(tcp_context->msn); \
ipcom_memcpy(&pkt->data[pointer], &ldata1, 2); \
pointer --; \
ipcom_memcpy(&pkt->data[pointer], &tcp_context->flags, 1); \
\
/* Reserverd field */ \
ldata = 0; \
ldata = (Ip_u8)(ldata | (tcp_context->offset_res & 0x0F)); \
/* Add c_flags, URP_ZERO, ACK_ZERO, ECN_USED */ \
ldata = (Ip_u8)(ldata | (tcp_context->c_flags & 0xF0)); \
/* Add ACK_STRIDE_FLAG */ \
if (tcp_context->tcp_flags & ACK_STRIDE_IRREG) \
ldata = ldata | 0x40; \
pointer --; \
ipcom_memcpy(&pkt->data[pointer], &ldata, 1); \
}
/*
*===========================================================================
* IPROHC_FMT_TCP_STATIC
*===========================================================================
* Fomat dynamic chain in a IR/IR-DYN packet
*
*/
#define IPROHC_FMT_TCP_STATIC(tcp_context, pointer, pkt) \
{ \
pointer -= 2; \
ipcom_memcpy(&pkt->data[pointer], &tcp_context->dst_port, 2); \
pointer -= 2; \
ipcom_memcpy(&pkt->data[pointer], &tcp_context->src_port, 2); \
}
/*
*===========================================================================
* IPROHC_FMT_TCP_IP_STATIC
*===========================================================================
* Fomat Static chain in a IR packet
*/
#define IPROHC_FMT_TCP_IP_STATIC(ip_context, pointer, pkt) \
{ \
Iprohc_ip_header *ip_header, *p_ip_header; \
\
for (ip_header = IPCOM_LIST_LAST(&ip_context->ip_head); ip_header; \
ip_header = p_ip_header) \
{ \
p_ip_header = IPCOM_LIST_PREV(&ip_header->ip_list); \
\
if (ip_header->has_exten) \
IPROHC_FMT_TCP_IP_EXT_STATIC(ip_header, pkt, pointer); \
\
if (ip_header->packet_type == ROHC_PKT_IPV4) \
{ \
/* Move pointer back for one IPv4 static part */ \
pointer -= 10; \
\
/* Add an IPv4 static part to static chain */ \
IPROHC_FMT_TCP_IPV4_STATIC(ip_header, &pkt->data[pointer]); \
} \
else \
{ \
/* Add an IPv6 static part to static chain */ \
IPROHC_FMT_TCP_IPV6_STATIC(ip_header, pkt, pointer); \
} \
} \
}
/*
*===========================================================================
* IPROHC_FMT_TCP_IPV4_STATIC
*===========================================================================
* Add an IPv4 static part to Static chain in a IR packet
*
* IPv4 header static part format
*
* COMPRESSED ipv4_static {
* version_flag =:= '0' [ 1 ];
* reserved =:= '0000000' [ 7 ];
* protocol =:= irregular(8) [ 8 ];
* src_addr =:= irregular(32) [ 32 ];
* dst_addr =:= irregular(32) [ 32 ];
* }
*
*/
#ifdef IPCOM_USE_INET
#define IPROHC_FMT_TCP_IPV4_STATIC(ip_header, data) \
{ \
Ipcom_ip_header *ip4_header = &(ip_header->header.ip4); \
Ip_u8 *buff = (Ip_u8 *)data; \
\
ipcom_memcpy(&buff[6], &ip4_header->dst, 4); \
ipcom_memcpy(&buff[2], &ip4_header->src, 4); \
buff[1] = ip4_header->protocol; \
buff[0] = 0x00; \
}
#else
#define IPROHC_FMT_TCP_IPV4_STATIC(ip_header, data) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_FMT_IPV6_STATIC
*===========================================================================
* Add an IPv6 static part to Static chain in a IR packet
*
* IPv6 header static part format
*
* COMPRESSED ipv6_static {
* version_flag =:= '1' [ 1 ];
* reserved =:= '00' [ 2 ];
* flow_label =:= fl_enc [ 5, 21 ];
* next_header =:= irregular(8) [ 8 ];
* src_addr =:= irregular(128) [ 128 ];
* dst_addr =:= irregular(128) [ 128 ];
* }
*
*/
#ifdef IPCOM_USE_INET6
#define IPROHC_FMT_TCP_IPV6_STATIC(ip_header, pkt, pointer) \
{ \
Ipcom_ip6_header *ip6_header = &(ip_header->header.ip6); \
Ip_u32 flow; \
Ip_u16 flow_lsb; \
Ip_u8 *buff; \
\
flow = IP_GET_NTOHL(&ip6_header->ver_class_flow) & 0xfffff; \
if (flow != 0) \
{ \
pointer -= 36; \
} \
else \
{ \
pointer -= 34; \
} \
\
buff = &pkt->data[pointer]; \
buff[0] = 0x80; \
if (flow != 0) \
{ \
/* fl_enc */ \
buff[0] = buff[0] | 0x10; \
buff[0] = (Ip_u8)(buff[0] | ((flow >> 16) & 0x0f)); \
flow_lsb = (Ip_u16)(flow & 0xffff); \
flow_lsb = ipcom_htons(flow_lsb); \
ipcom_memcpy(&buff[1], &flow_lsb, 2); \
buff[3] = ip6_header->nxt; \
ipcom_memcpy(&buff[4], &ip6_header->src, 16); \
ipcom_memcpy(&buff[20], &ip6_header->dst, 16); \
} \
else \
{ \
/* fl_enc */ \
buff[1] = ip6_header->nxt; \
ipcom_memcpy(&buff[2], &ip6_header->src, 16); \
ipcom_memcpy(&buff[18], &ip6_header->dst, 16); \
} \
}
#else
#define IPROHC_FMT_TCP_IPV6_STATIC(ip_header, pkt, pointer) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_FMT_TCP_IP_EXT_STATIC
*===========================================================================
*
*/
#define IPROHC_FMT_TCP_IP_EXT_STATIC(ip_header, pkt, pointer) \
{ \
Iprohc_ref_list *ext, *n_ext; \
\
for (ext = IPCOM_LIST_LAST(&ip_header->ref_head); \
ext; \
ext = n_ext) \
{ \
n_ext = IPCOM_LIST_PREV(&ext->ref_list); \
\
switch(ext->type) \
{ \
case IP_IPPROTO_DSTOPTS: /* dest_opt, hop_op */ \
case IP_IPPROTO_HOPOPTS: \
pointer -= 2; \
ipcom_memcpy(&pkt->data[pointer], &ext->data[0], 2); \
break; \
case IP_IPPROTO_ROUTING: /* rout_op */ \
pointer = pointer - ext->length; \
ipcom_memcpy(&pkt->data[pointer], &ext->data[0], ext->length); \
break; \
case IP_IPPROTO_MOBILE: /* checksum is inferred */ \
if(ext->data[1] & 0x80) \
{ \
pointer = pointer - 8; \
ipcom_memcpy(&pkt->data[pointer], &ext->data[4], 8); \
} \
else \
{ \
pointer = pointer - 4; \
ipcom_memcpy(&pkt->data[pointer], &ext->data[4], 4); \
} \
/* Skip Checksum */ \
pointer -= 2; \
ipcom_memcpy(&pkt->data[pointer], &ext->data[0], 2); \
break; \
default: \
/* Not supported extension */ \
break; \
} \
} \
}
/*
*===========================================================================
* IPROHC_FMT_TCP_IP_DYNAMC
*===========================================================================
* Format Dynamic chain in a IR/IR-DYN packet
*/
#define IPROHC_FMT_TCP_IP_DYNAMC(ip_context, pointer, pkt) \
{ \
Iprohc_ip_header *ip_header, *p_ip_header; \
\
for (ip_header = IPCOM_LIST_LAST(&ip_context->ip_head); \
ip_header != IP_NULL; \
ip_header = p_ip_header) \
{ \
p_ip_header = IPCOM_LIST_PREV(&ip_header->ip_list); \
\
if (ip_header->has_exten) \
IPROHC_FMT_TCP_IP_EXT_DYNAMIC(ip_header, pkt, pointer); \
\
if (ip_header->packet_type == ROHC_PKT_IPV4) \
{ \
/* Add an IPv4 dynamic part to Dynamic chain */ \
IPROHC_FMT_TCP_IPV4_DYNAMIC(ip_header, pkt, pointer); \
} \
else \
{ \
/* Move pointer back for one IPv6 dynamic part */ \
pointer = pointer - 2; \
\
/* Add an IPv6 dynamic part to Dynamic chain */ \
IPROHC_FMT_TCP_IPV6_DYNAMIC(ip_header, pkt, pointer); \
} \
} \
}
/*
*===========================================================================
* IPROHC_FMT_TCP_IPV4_DYNAMIC
*===========================================================================
* Add an IPv4 dynamic part to Dynamic chain in a IR/IR-DYN packet
*
* COMPRESSED ipv4_dynamic {
* reserved =:= '00000' [ 5 ];
* df =:= irregular(1) [ 1 ];
* ip_id_behavior =:= ip_id_behavior_choice(is_innermost) [ 2 ];
* dscp =:= irregular(6) [ 6 ];
* ip_ecn_flags =:= irregular(2) [ 2 ];
* ttl_hopl =:= irregular(8) [ 8 ];
* ip_id =:=
* ip_id_enc_dyn(ip_id_behavior.UVALUE) [ 0, 16 ];
* }
*
*/
#ifdef IPCOM_USE_INET
#define IPROHC_FMT_TCP_IPV4_DYNAMIC(ip_header, pkt, pointer) \
{ \
Ip_u8 ip_id_type = 100; \
Ipcom_ip_header *ip4_header = &(ip_header->header.ip4); \
\
if (ip_header->rnd) \
ip_id_type = IP_ID_BEHAVIOR_RANDOM; \
else if (ip_header->nbo) \
ip_id_type = IP_ID_BEHAVIOR_SEQUENTIAL; \
else if (ip_header->sid) \
{ \
ip_id_type = IP_ID_BEHAVIOR_ZERO; \
goto m2; \
} \
else \
{ \
/* Not supported IP ID type (swapped bytes). Use random type. */ \
ip_id_type = IP_ID_BEHAVIOR_RANDOM; \
} \
\
if(ip_id_type != IP_ID_BEHAVIOR_ZERO) \
{ \
pointer = pointer - 2; \
ipcom_memcpy(&pkt->data[pointer], &(ip4_header->id), 2); \
} \
m2: \
pointer--; \
pkt->data[pointer] = ip4_header->ttl; \
pointer--; \
pkt->data[pointer] = ip4_header->tos; \
pointer--; \
pkt->data[pointer] = 0; \
if (ip4_header->frag & IPCOM_IPFRAG_DF) pkt->data[pointer] = 0x04; \
pkt->data[pointer] = (Ip_u8)(pkt->data[pointer] | (ip_id_type & 0x03)); \
}
#else
#define IPROHC_FMT_TCP_IPV4_DYNAMIC(ip_header, pkt, pointer) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_FMT_TCP_IPV6_DYNAMIC
*===========================================================================
* Add an IPv6 dynamic part to dynamic chain in a IR/IR-DYN packet
*
* COMPRESSED ipv6_dynamic {
* dscp =:= irregular(6) [ 6 ];
* ip_ecn_flags =:= irregular(2) [ 2 ];
* ttl_hopl =:= irregular(8) [ 8 ];
* }
*/
#ifdef IPCOM_USE_INET6
#define IPROHC_FMT_TCP_IPV6_DYNAMIC(ip_header, pkt, pointer) \
{ \
Ipcom_ip6_header *ip6_header; \
\
ip6_header = (Ipcom_ip6_header *)&(ip_header->header.ip6); \
/* Add dscp and ip_ecn_flags */ \
pkt->data[pointer] = (Ip_u8)((IP_GET_NTOHL(&ip6_header->ver_class_flow) >> 20) & 0xff); \
pkt->data[pointer + 1] = ip6_header->hlim; \
}
#else
#define IPROHC_FMT_TCP_IPV6_DYNAMIC(ip_header, pkt, pointer) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_FMT_TCP_IP_EXT_DYNAMIC
*===========================================================================
*
*/
#define IPROHC_FMT_TCP_IP_EXT_DYNAMIC(ip_header, pkt, pointer) \
{ \
Iprohc_ref_list *ext_hdr, *n_ext_hdr; \
\
for (ext_hdr = IPCOM_LIST_LAST(&ip_header->ref_head); \
ext_hdr; \
ext_hdr = n_ext_hdr) \
{ \
n_ext_hdr = IPCOM_LIST_PREV(&ext_hdr->ref_list); \
\
switch(ext_hdr->type) \
{ \
/* Mine and IP_IPPROTO_ROUTING do not have dynamic content */ \
case IP_IPPROTO_DSTOPTS: /* dest_opt, hop_op */ \
case IP_IPPROTO_HOPOPTS: \
pointer = pointer - (ext_hdr->length - 2); \
ipcom_memcpy(&pkt->data[pointer], &ext_hdr->data[2], \
(Ip_size_t)(ext_hdr->length - 2)); \
break; \
default: \
break; \
} \
} \
}
/*
*===========================================================================
* IPROHC_GET_TCP_IP_STATIC
*===========================================================================
* Get Static chain in a IR packet
*
* IPv4 header static part format
*
* COMPRESSED ipv4_static {
* version_flag =:= '0' [ 1 ];
* reserved =:= '0000000' [ 7 ];
* protocol =:= irregular(8) [ 8 ];
* src_addr =:= irregular(32) [ 32 ];
* dst_addr =:= irregular(32) [ 32 ];
* }
*
*/
#define IPROHC_GET_TCP_IP_STATIC(ip_context, pointer, pkt) \
{ \
Iprohc_ip_header *ip_header_v; \
Ip_u8 protocol; \
\
while (((pkt->data[pointer] >> 7) == 0) || \
((pkt->data[pointer] >> 7) == 1)) \
{ \
ip_header_v = (Iprohc_ip_header *)ipcom_malloc(sizeof(Iprohc_ip_header)); \
if (ip_header_v == IP_NULL) \
{ \
IPCOM_LOG0(ERR,"IPROHC_GET_TCP_IP_STATIC, out of memory(header)"); \
goto errout; \
} \
\
/* Pre-init the memory */ \
ipcom_memset(ip_header_v, 0, sizeof(Iprohc_ip_header));\
ipcom_list_init(&ip_header_v->ref_head); \
\
/* Add the header to the context list */ \
ipcom_list_insert_last(&ip_context->ip_head, &ip_header_v->ip_list); \
ip_context->ip_num++; \
\
if ((pkt->data[pointer] >> 7) == 0) \
{ \
protocol = pkt->data[pointer+1]; \
\
/* IPv4 header */ \
/* This macro should not change protocol val */ \
IPROHC_GET_TCP_IPV4_STATIC(ip_header_v, pointer, pkt, protocol); \
} \
else \
{ \
/* fl_enc encoding */ \
if (pkt->data[pointer] & 0x10) \
{ \
protocol = pkt->data[pointer+3]; \
} \
else \
{ \
protocol = pkt->data[pointer+1]; \
} \
\
/* IPv4 header */ \
/* This macro should not change protocol val */ \
IPROHC_GET_TCP_IPV6_STATIC(ip_header_v, pointer, pkt, protocol); \
} \
\
if ((ip_header_v->has_exten == IP_TRUE) && (IPROHC_PROC_EXT(protocol))) \
IPROHC_GET_TCP_IP_EXT_STATIC(ip_header_v, pointer, pkt, protocol); \
\
if ((protocol != IP_IPPROTO_IPIP) && \
(protocol != IP_IPPROTO_IPV6)) \
break; \
} \
}
/*
*===========================================================================
* IPROHC_GET_TCP_IPV4_STATIC
*===========================================================================
* Get an IPv4 static part in Static chain from a IR packet
*
* COMPRESSED ipv4_static {
* version_flag =:= '0' [ 1 ];
* reserved =:= '0000000' [ 7 ];
* protocol =:= irregular(8) [ 8 ];
* src_addr =:= irregular(32) [ 32 ];
* dst_addr =:= irregular(32) [ 32 ];
* }
*
*/
#ifdef IPCOM_USE_INET
#define IPROHC_GET_TCP_IPV4_STATIC(iprohc_header, pointer, pkt, protocol) \
{ \
Ipcom_ip_header *ip4_header = &(iprohc_header->header.ip4); \
\
iprohc_header->packet_type = ROHC_PKT_IPV4; \
/* version = 4, IHL = 5 */ \
ip4_header->vers_len = 0x45; \
ip4_header->protocol = pkt->data[pointer+1]; \
\
if (IPROHC_PROC_EXT(ip4_header->protocol)) \
iprohc_header->has_exten = IP_TRUE; \
else if (iprohc_header->has_exten) \
{ \
/* Free the old IP extension headers */ \
IPROHC_FREE_REF_LIST(iprohc_header); \
iprohc_header->has_exten = IP_FALSE; \
} \
\
/* Copy source and destination address */ \
ipcom_memcpy(&ip4_header->src, &pkt->data[pointer+2], 4); \
ipcom_memcpy(&ip4_header->dst, &pkt->data[pointer+6], 4); \
\
/* Move the pointer */ \
pointer = pointer + 10; \
}
#else
#define IPROHC_GET_TCP_IPV4_STATIC(iprohc_header, pointer, pkt, protocol) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_GET_TCP_IPV6_STATIC
*===========================================================================
* Get an IPv6 static part in Static chain from a IR packet
*
* COMPRESSED ipv6_static {
* version_flag =:= '1' [ 1 ];
* reserved =:= '00' [ 2 ];
* flow_label =:= fl_enc [ 5, 21 ];
* next_header =:= irregular(8) [ 8 ];
* src_addr =:= irregular(128) [ 128 ];
* dst_addr =:= irregular(128) [ 128 ];
* }
*
*/
#ifdef IPCOM_USE_INET6
#define IPROHC_GET_TCP_IPV6_STATIC(iprohc_header, pointer, pkt, protocol) \
{ \
Ipcom_ip6_header *ip6_header = &(iprohc_header->header.ip6); \
Ip_u32 flow = 0; \
Ip_u16 flow_lsb = 0; \
\
iprohc_header->packet_type = ROHC_PKT_IPV6; \
\
/* fl_enc encoding */ \
if (pkt->data[pointer] & 0x10) \
{ \
/* Form the flow label */ \
ipcom_memcpy(&flow_lsb, &pkt->data[pointer + 1], 2); \
flow = (Ip_u32)ipcom_ntohs(flow_lsb); \
flow = flow | (Ip_u32)((pkt->data[pointer] & (Ip_u8)0xFF) << 16); \
pointer = pointer + 3; \
} \
else \
{ \
pointer ++; \
} \
\
ip6_header->nxt = pkt->data[pointer]; \
pointer ++; \
flow = (6<<28) | flow; \
ip6_header->ver_class_flow = ip_htonl(flow); \
\
if (IPROHC_PROC_EXT(ip6_header->nxt)) \
iprohc_header->has_exten = IP_TRUE; \
else if (iprohc_header->has_exten) \
{ \
/* Free the old IP extension headers */ \
IPROHC_FREE_REF_LIST(iprohc_header); \
iprohc_header->has_exten = IP_FALSE; \
} \
\
/* copy source and destination addresses */ \
ipcom_memcpy(&ip6_header->src, &pkt->data[pointer], 16); \
ipcom_memcpy(&ip6_header->dst, &pkt->data[pointer+16], 16); \
pointer = pointer + 32; \
}
#else
#define IPROHC_GET_TCP_IPV6_STATIC(iprohc_header, pointer, pkt, protocol) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_GET_TCP_IP_EXT_STATIC
*===========================================================================
*
*
*/
#define IPROHC_GET_TCP_IP_EXT_STATIC(iprohc_header, pointer, pkt, protocol) \
{ \
Iprohc_ip_header tmp_ip_header; \
Ip_u8 proto; \
Iprohc_ref_list *ref_list; \
Ip_bool err = IP_FALSE; \
Ip_u16 mine_c; \
\
proto = protocol; \
ipcom_memset(&tmp_ip_header, 0, sizeof(Iprohc_ip_header)); \
ipcom_list_init(&tmp_ip_header.ref_head); \
while (IPROHC_PROC_EXT(protocol)) \
{ \
/* Record the reference list */ \
ref_list = (Iprohc_ref_list *)ipcom_malloc(sizeof(Iprohc_ref_list)); \
if (ref_list == IP_NULL) \
{ \
IPCOM_LOG0(ERR, "IPROHC_UPD_TCP_IP_EXT_STATIC, out of memory(ref_list)"); \
err = IP_TRUE; \
goto l1; \
} \
\
ipcom_memset(ref_list, 0, sizeof(Iprohc_ref_list)); \
\
/* Add the ref list structure to ROHC IP header structure */ \
ipcom_list_insert_last(&tmp_ip_header.ref_head, &ref_list->ref_list); \
\
/* Record the IP extension header */ \
ref_list->type = protocol; \
protocol = pkt->data[pointer]; \
\
switch(ref_list->type) \
{ \
/* Dest_opt, hop_op */ \
case IP_IPPROTO_DSTOPTS: \
case IP_IPPROTO_HOPOPTS: \
/* Copy 2 bytes. The rest will be added from dynamic cheain */ \
ref_list->length = pkt->data[pointer + 1]; \
ref_list->length = (Ip_u8)(8 * ( ref_list->length + 1)); \
if((ref_list->data = ipcom_malloc(ref_list->length)) == IP_NULL) \
{ \
err = IP_TRUE; \
goto l1; \
} \
ipcom_memcpy(&ref_list->data[0], &pkt->data[pointer], 2); \
pointer = pointer + 2; \
break; \
/* Rout_op */ \
case IP_IPPROTO_ROUTING: \
ref_list->length = pkt->data[pointer + 1]; \
ref_list->length = (Ip_u8)(8 * ( ref_list->length + 1)); \
if((ref_list->data = ipcom_malloc(ref_list->length)) == IP_NULL) \
{ \
err = IP_TRUE; \
goto l1; \
} \
ipcom_memcpy(&ref_list->data[0], &pkt->data[pointer], ref_list->length); \
pointer = pointer + ref_list->length; \
break; \
/* Mine, checksum is inferred */ \
case IP_IPPROTO_MOBILE: \
/* Minimal encapsulation header */ \
/* Skip Checksum */ \
if (pkt->data[pointer + 1] & 0x80) \
ref_list->length = 12; \
else \
ref_list->length = 8; \
\
if((ref_list->data = ipcom_malloc(ref_list->length)) == IP_NULL) \
{ \
err = IP_TRUE; \
goto l1; \
} \
ipcom_memcpy(&ref_list->data[0], &pkt->data[pointer], 2); \
pointer = pointer + 2; \
/* Null checksum headers */ \
ref_list->data[2] = 0; \
ref_list->data[3] = 0; \
\
if (ref_list->data[1] & 0x80) \
{ \
ipcom_memcpy(&ref_list->data[4], &pkt->data[pointer], 8); \
pointer = pointer + 8; \
} \
else \
{ \
ipcom_memcpy(&ref_list->data[4], &pkt->data[pointer], 4); \
pointer = pointer + 4; \
} \
/* Calculate Mine checksum */ \
mine_c = ipcom_in_checksum(&ref_list->data[0], ref_list->length); \
/* mine_c = ipcom_htons(mine_c); */ \
ipcom_memcpy(&ref_list->data[2], &mine_c, 2); \
break; \
default: \
/* Not supported extension */ \
break; \
} \
\
tmp_ip_header.ref_num++; \
/* Total length of IP extension headers */ \
tmp_ip_header.ref_len = (Ip_u16)(tmp_ip_header.ref_len + ref_list->length); \
tmp_ip_header.has_exten = IP_TRUE; \
} \
l1: \
if(err == IP_FALSE) \
{ \
/* Free the old reference list */ \
IPROHC_FREE_REF_LIST(iprohc_header); \
/* Record the new one */ \
IPROHC_COPY_REF_LIST(iprohc_header, (&tmp_ip_header)); \
} \
else \
{ \
IPROHC_FREE_REF_LIST((&tmp_ip_header)); \
IPCOM_LOG0(ERR, "IPROHC_GET_LIST_ET0, out of memory(ref->data)"); \
/* Free the new reference list */ \
} \
}
/*
*===========================================================================
* IPROHC_GET_TCP_IP_DYNAMIC
*===========================================================================
* Get Dynamic chain in a IR/IP-DYN packet
*/
#define IPROHC_GET_TCP_IP_DYNAMIC(ip_context, pointer, pkt) \
{ \
Iprohc_ip_header *ip_header_v, *p_ip_header; \
\
for (ip_header_v = IPCOM_LIST_FIRST(&ip_context->ip_head); ip_header_v; \
ip_header_v = p_ip_header) \
{ \
p_ip_header = IPCOM_LIST_NEXT(&ip_header_v->ip_list); \
\
if (ip_header_v->packet_type == ROHC_PKT_IPV4) \
{ \
/* Get an IPv4 dynamic part */ \
IPROHC_GET_TCP_IPV4_DYNAMIC(ip_header_v, pointer, pkt); \
} \
else \
{ \
/* Get an IPv6 dynamic part */ \
IPROHC_GET_TCP_IPV6_DYNAMIC(ip_header_v, pointer, pkt); \
} \
} \
}
/*
*===========================================================================
* IPROHC_GET_TCP_IPV4_DYNAMIC
*===========================================================================
* Get an IPv4 dynamic part in Dynamic chain from a IR/IR-DYN packet
*
* COMPRESSED ipv4_dynamic {
* reserved =:= '00000' [ 5 ];
* df =:= irregular(1) [ 1 ];
* ip_id_behavior =:= ip_id_behavior_choice(is_innermost) [ 2 ];
* dscp =:= irregular(6) [ 6 ];
* ip_ecn_flags =:= irregular(2) [ 2 ];
* ttl_hopl =:= irregular(8) [ 8 ];
* ip_id =:=
* ip_id_enc_dyn(ip_id_behavior.UVALUE) [ 0, 16 ];
* }
*
*/
#ifdef IPCOM_USE_INET
#define IPROHC_GET_TCP_IPV4_DYNAMIC(iprohc_header, pointer, pkt) \
{ \
Ipcom_ip_header *ip4_header = &(iprohc_header->header.ip4); \
Ip_u8 ip_id_behavior; \
\
if (pkt->data[pointer] & 0x04) \
ip4_header->frag = (Ip_u16)(ip4_header->frag | IPCOM_IPFRAG_DF); \
else ip4_header->frag = (Ip_u16)(ip4_header->frag & (~IPCOM_IPFRAG_DF)); \
\
iprohc_header->rnd = IP_FALSE; \
iprohc_header->nbo = IP_FALSE; \
iprohc_header->sid = IP_FALSE; \
\
ip_id_behavior = (Ip_u8)(pkt->data[pointer] & 0x03); \
pointer ++; \
ip4_header->tos = pkt->data[pointer]; \
pointer ++; \
ip4_header->ttl = pkt->data[pointer]; \
pointer ++; \
\
if (ip_id_behavior == IP_ID_BEHAVIOR_SEQUENTIAL) \
iprohc_header->nbo = IP_TRUE; \
else if (ip_id_behavior == IP_ID_BEHAVIOR_RANDOM) \
iprohc_header->rnd = IP_TRUE; \
else if (ip_id_behavior == IP_ID_BEHAVIOR_ZERO) \
iprohc_header->sid = IP_TRUE; \
/* ip_id_behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED not supported */ \
\
/* ip_id_enc_dyn compression */ \
if(ip_id_behavior == IP_ID_BEHAVIOR_ZERO) \
ip4_header->id = 0; \
else \
{ \
ipcom_memcpy(&(ip4_header->id), &(pkt->data[pointer]), 2); \
pointer = pointer + 2; \
} \
\
if (iprohc_header->has_exten) \
IPROHC_GET_TCP_IP_EXT_DYNAMIC(iprohc_header, ip4_header->protocol, \
pointer, pkt); \
}
#else
#define IPROHC_GET_TCP_IPV4_DYNAMIC(iprohc_header, pointer, pkt) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_GET_TCP_IPV6_DYNAMIC
*===========================================================================
* Get an IPv6 dynamic part in Dynamic chain from a IR/IR-DYN packet
*
* COMPRESSED ipv6_dynamic {
* dscp =:= irregular(6) [ 6 ];
* ip_ecn_flags =:= irregular(2) [ 2 ];
* ttl_hopl =:= irregular(8) [ 8 ];
* }
*
*/
#ifdef IPCOM_USE_INET6
#define IPROHC_GET_TCP_IPV6_DYNAMIC(iprohc_header, pointer, pkt) \
{ \
Ipcom_ip6_header *ip6_header; \
Ip_u32 ver_class_flow; \
\
ip6_header = (Ipcom_ip6_header *)&(iprohc_header->header.ip6); \
ver_class_flow = ip_ntohl(ip6_header->ver_class_flow); \
\
/* Add traffic class (8 bits) to ver_class_flow */ \
ver_class_flow = ver_class_flow | (Ip_u32)((pkt->data[pointer])<<20); \
ip6_header->ver_class_flow = ip_htonl(ver_class_flow); \
pointer ++; \
ip6_header->hlim = pkt->data[pointer]; \
pointer ++; \
\
if (iprohc_header->has_exten) \
IPROHC_GET_TCP_IP_EXT_DYNAMIC(iprohc_header, ip6_header->nxt, pointer, pkt); \
}
#else
#define IPROHC_GET_TCP_IPV6_DYNAMIC(iprohc_header, pointer, pkt) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_GET_TCP_IP_EXT_DYNAMIC
*===========================================================================
* Update the compressed list encoding type 0
*
*/
#define IPROHC_GET_TCP_IP_EXT_DYNAMIC(iprohc_header, protocol, pointer, pkt) \
{ \
Iprohc_ref_list *ext_hdr, *n_ext_hdr; \
Ip_u8 next_hdr_tmp = protocol; \
\
for (ext_hdr = IPCOM_LIST_FIRST(&iprohc_header->ref_head); \
ext_hdr; \
ext_hdr = n_ext_hdr) \
{ \
n_ext_hdr = IPCOM_LIST_NEXT(&ext_hdr->ref_list); \
\
switch(next_hdr_tmp) \
{ \
case IP_IPPROTO_DSTOPTS: /* dest_opt, hop_op */ \
case IP_IPPROTO_HOPOPTS: \
ipcom_memcpy(&ext_hdr->data[2], &pkt->data[pointer], (Ip_size_t)(ext_hdr->length - 2)); \
pointer = pointer + ext_hdr->length - 2; \
break; \
case IP_IPPROTO_ROUTING: /* No dynamic content */ \
case IP_IPPROTO_MOBILE: /* No dynamic content */ \
break; \
default: \
/* Not supported extension */ \
break; \
} \
next_hdr_tmp = ext_hdr->type; \
} \
}
/*
*===========================================================================
* IPROHC_UPD_TCP_IP_STATIC
*===========================================================================
* Update Static chains from a IR packet
*/
#define IPROHC_UPD_TCP_IP_STATIC(ip_context, pointer, pkt) \
{ \
Iprohc_ip_header *ip_header, *p_ip_header; \
Ip_u8 protocol; \
\
for (ip_header = IPCOM_LIST_FIRST(&ip_context->ip_head); ip_header; \
ip_header = p_ip_header) \
{ \
p_ip_header = IPCOM_LIST_NEXT(&ip_header->ip_list); \
\
if (ip_header->packet_type == ROHC_PKT_IPV4) \
{ \
/* Update an IPv4 static part */ \
protocol = pkt->data[pointer+1]; \
/* This macro should not change protocol val */ \
IPROHC_GET_TCP_IPV4_STATIC(ip_header, pointer, pkt, protocol); \
} \
else \
{ \
/* Update an IPv6 static part */ \
/* fl_enc encoding */ \
if (pkt->data[pointer] & 0x10) \
{ \
protocol = pkt->data[pointer+3]; \
} \
else \
{ \
protocol = pkt->data[pointer+1]; \
} \
/* This macro should not change protocol val */ \
IPROHC_GET_TCP_IPV6_STATIC(ip_header, pointer, pkt, protocol); \
} \
if ((ip_header->has_exten == IP_TRUE) && (IPROHC_PROC_EXT(protocol))) \
IPROHC_GET_TCP_IP_EXT_STATIC(ip_header, pointer, pkt, protocol); \
} \
}
/*
*===========================================================================
* IPROHC_UPD_TCP_IP_DYNAMIC
*===========================================================================
* Compressor. Set context attributes for scailed SN and ACK
*/
#define IPROHC_UPD_TCP_IP_DYNAMIC(ip_context, pointer, pkt) \
{ \
IPROHC_GET_TCP_IP_DYNAMIC(ip_context, pointer, pkt); \
}
/*
*===========================================================================
* IPROHC_TCP_C_INIT_SCALING
*===========================================================================
* Compressor. Set context attributes for scailed SN and ACK
*/
#define IPROHC_TCP_C_INIT_SCALING(tcp_context, pkt) \
{ \
/* Scaling is not supported */ \
tcp_context->scailing_used = IP_FALSE; \
tcp_context->ackn_stride = 0; \
/*Clear ACK_STRIDE_IRREG flag */ \
tcp_context->tcp_flags = (Ip_u8)(tcp_context->tcp_flags & (~ACK_STRIDE_IRREG)); \
}
/*
*===========================================================================
* IPROHC_TCP_D_INIT_SCALING
*===========================================================================
* Compressor. Set context attributes for scailed SN and ACK
*/
#define IPROHC_TCP_D_INIT_SCALING(tcp_context, pkt) \
{ \
/* Scaling is not supported yet */ \
tcp_context->scailing_used = IP_FALSE; \
}
/*
*===========================================================================
* IPROHC_TCP_C_COPY_OPT_LIST
*===========================================================================
* Copy the TCP options list
*/
#define IPROHC_TCP_C_COPY_OPT_LIST(tcp_context, from_tcp_context) \
{ \
tcp_item_list *opt_item, *n_opt_item; \
\
ipcom_list_init(&tcp_context->opt); \
tcp_context->pad_ln = from_tcp_context->pad_ln; \
tcp_context->opt_num = from_tcp_context->opt_num; \
tcp_context->max_indx = from_tcp_context->max_indx; \
/* Copy gen indexes */ \
ipcom_memcpy(&tcp_context->item_gen_uindex, \
&from_tcp_context->item_gen_uindex, \
GEN_LEN); \
\
for (opt_item = IPCOM_LIST_FIRST(&from_tcp_context->opt); \
opt_item; \
opt_item = n_opt_item) \
{ \
n_opt_item = IPCOM_LIST_NEXT(&opt_item->item_list); \
\
ipcom_list_remove(&opt_item->item_list); \
/* Add the item structure to tcp context */ \
ipcom_list_insert_last(&tcp_context->opt, &opt_item->item_list); \
} \
}
/*
*===========================================================================
* IPROHC_TCP_C_FREE_OPT_LIST
*===========================================================================
*
*/
#define IPROHC_TCP_C_FREE_OPT_LIST(tcp_context) \
{ \
tcp_item_list *opt_item, *n_opt_item; \
\
tcp_context->pad_ln = 0; \
tcp_context->opt_num = 0; \
tcp_context->max_indx = 0; \
ipcom_memset(&tcp_context->item_gen_uindex, 0, GEN_LEN); \
\
for (opt_item = IPCOM_LIST_FIRST(&tcp_context->opt); \
opt_item; \
opt_item = n_opt_item) \
{ \
n_opt_item = IPCOM_LIST_NEXT(&opt_item->item_list); \
ipcom_list_remove(&opt_item->item_list); \
\
if (opt_item->item) ipcom_free(opt_item->item); \
\
ipcom_free(opt_item); \
} \
\
}
/*
*===========================================================================
* IPROHC_TCP_C_FREE_OPT_LIST
*===========================================================================
*
*/
#define IPROHC_TCP_C_FREE_OPT_LIST1(tcp_opt_list) \
{ \
tcp_item_list *opt_item, *n_opt_item; \
\
tcp_opt_list->pad_ln = 0; \
tcp_opt_list->opt_num = 0; \
tcp_opt_list->max_indx = 0; \
ipcom_memset(&tcp_opt_list->item_gen_uindex, 0, GEN_LEN); \
\
for (opt_item = IPCOM_LIST_FIRST(&tcp_opt_list->opt); \
opt_item; \
opt_item = n_opt_item) \
{ \
n_opt_item = IPCOM_LIST_NEXT(&opt_item->item_list); \
ipcom_list_remove(&opt_item->item_list); \
\
if (opt_item->item) \
ipcom_free(opt_item->item); \
\
ipcom_free(opt_item); \
} \
}
/*
*===========================================================================
* IPROHC_TCP_D_FREE_OPT_LIST
*===========================================================================
*
*/
#define IPROHC_TCP_D_FREE_OPT_LIST(tcp_context) \
{ \
tcp_item_list *opt_item, *n_opt_item; \
\
tcp_context->pad_ln = 0; \
tcp_context->opt_num = 0; \
ipcom_memset(&tcp_context->item_gen_uindex, 0, GEN_LEN); \
\
for (opt_item = IPCOM_LIST_FIRST(&tcp_context->opt); \
opt_item; \
opt_item = n_opt_item) \
{ \
n_opt_item = IPCOM_LIST_NEXT(&opt_item->item_list); \
ipcom_list_remove(&opt_item->item_list); \
\
if (opt_item->item) ipcom_free(opt_item->item); \
\
ipcom_free(opt_item); \
} \
}
/*
*===========================================================================
* IPROHC_TCP_D_FREE_OPT_LIST
*===========================================================================
*
*/
#define IPROHC_TCP_D_FREE_OPT_LIST1(tmp_opt_list) \
{ \
tcp_item_list *opt_item, *n_opt_item; \
\
tmp_opt_list.pad_ln = 0; \
tmp_opt_list.opt_num = 0; \
\
for (opt_item = IPCOM_LIST_FIRST(&tmp_opt_list.opt); \
opt_item; \
opt_item = n_opt_item) \
{ \
n_opt_item = IPCOM_LIST_NEXT(&opt_item->item_list); \
ipcom_list_remove(&opt_item->item_list); \
\
if (opt_item->item) \
ipcom_free(opt_item->item); \
\
ipcom_free(opt_item); \
} \
}
/*
*===========================================================================
* IPROHC_TCP_D_COPY_OPT_LIST
*===========================================================================
*
*/
#define IPROHC_TCP_D_COPY_OPT_LIST(tcp_context, from_opt_list) \
{ \
tcp_item_list *opt_item, *n_opt_item; \
\
ipcom_list_init(&tcp_context->opt); \
tcp_context->pad_ln = from_opt_list.pad_ln; \
tcp_context->opt_num = from_opt_list.opt_num; \
\
ipcom_memcpy(&tcp_context->item_gen_uindex, \
&from_opt_list.item_gen_uindex, GEN_LEN); \
\
for (opt_item = IPCOM_LIST_FIRST(&from_opt_list.opt); \
opt_item; \
opt_item = n_opt_item) \
{ \
n_opt_item = IPCOM_LIST_NEXT(&opt_item->item_list); \
/* Remove the item from the list */ \
ipcom_list_remove(&opt_item->item_list); \
/* Add the ref list structure to to_ref_head */ \
ipcom_list_insert_last(&tcp_context->opt, &opt_item->item_list); \
} \
}
/*
*===========================================================================
* IPROHC_GET_TCP_STATIC
*===========================================================================
* GET static header header part in a IR packet
*/
#define IPROHC_GET_TCP_STATIC(tcp_context, pointer, pkt) \
{ \
ipcom_memcpy(&tcp_context->src_port, &pkt->data[pointer], 2); \
pointer = pointer + 2; \
ipcom_memcpy(&tcp_context->dst_port, &pkt->data[pointer], 2); \
pointer = pointer + 2; \
}
/*
*===========================================================================
* IPROHC_GET_TCP_DYNAMIC
*===========================================================================
* Get TCP dynamic chain in a IR/IP-DYN packet
*/
#define IPROHC_GET_TCP_DYNAMIC(tcp_context, pointer, pkt) \
{ \
Ip_u16 data = 0; \
Ip_err ret_val = IPCOM_SUCCESS; \
tcp_opt_list tmp_opt_list; \
\
/* Get c_flags, URP_ZERO, ACK_ZERO, ECN_USED */ \
tcp_context->c_flags = (Ip_u8)(tcp_context->c_flags & (~0xF0)); \
tcp_context->c_flags = (Ip_u8)(tcp_context->c_flags | \
(pkt->data[pointer] & 0xF0)); \
/* Get ACK_STRIDE_FLAG */ \
tcp_context->tcp_flags = (Ip_u8)(tcp_context->tcp_flags & (~ACK_STRIDE_IRREG)); \
if (pkt->data[pointer] & 0x40) \
tcp_context->tcp_flags = tcp_context->tcp_flags | ACK_STRIDE_IRREG; \
\
tcp_context->offset_res = (Ip_u8)(tcp_context->offset_res & (~0x0F)); \
tcp_context->offset_res = (Ip_u8)(tcp_context->offset_res | \
(pkt->data[pointer] & 0x0F)); \
\
pointer++; \
ipcom_memcpy(&tcp_context->flags, &pkt->data[pointer], 1); \
pointer++; \
/* MSN */ \
ipcom_memcpy(&data, &pkt->data[pointer], 2); \
tcp_context->msn = ipcom_ntohs(data); \
pointer = pointer + 2; \
/* Seq number */ \
ipcom_memcpy(&tcp_context->sn, &pkt->data[pointer], 4); \
pointer = pointer + 4; \
/* Ack number */ \
if(!(tcp_context->c_flags & ACK_ZERO)) \
{ \
ipcom_memcpy(&tcp_context->ackn, &pkt->data[pointer], 4); \
pointer = pointer + 4; \
} \
else tcp_context->ackn = 0; \
/* Window */ \
ipcom_memcpy(&tcp_context->window, &pkt->data[pointer], 2); \
pointer = pointer + 2; \
/* Checksum */ \
ipcom_memcpy(&tcp_context->chksum, &pkt->data[pointer], 2); \
pointer = pointer + 2; \
\
if(!(tcp_context->c_flags & URP_ZERO)) \
{ \
ipcom_memcpy(&tcp_context->uptr, &pkt->data[pointer], 2); \
pointer += 2; \
} else tcp_context->uptr = 0; \
\
if(tcp_context->tcp_flags & ACK_STRIDE_IRREG) \
{ \
ipcom_memcpy(&tcp_context->ackn_stride, &pkt->data[pointer], 2); \
pointer += 2; \
} /* else ack_stride is a static. Leave the previouse value in the context */ \
\
/* Save the older OPT list and recover if the exctraction of the new OPT failes */ \
ipcom_memset(&tmp_opt_list, 0, sizeof(tmp_opt_list)); \
ipcom_list_init(&tmp_opt_list.opt); \
IPROHC_GET_LIST_TCP_OPT(tmp_opt_list, pkt, pointer, ret_val); \
\
if (ret_val == IPCOM_SUCCESS) \
{ \
IPROHC_TCP_D_FREE_OPT_LIST(tcp_context); \
IPROHC_TCP_D_COPY_OPT_LIST(tcp_context, tmp_opt_list); \
} \
else \
{ \
IPROHC_TCP_D_FREE_OPT_LIST1(tmp_opt_list); \
goto errout; \
} \
}
/*
*===========================================================================
* IPROHC_GET_TCP_DYNAMIC
*===========================================================================
* Get TCP dynamic chain in a IR/IP-DYN packet
*/
#define IPROHC_GET_TCP_DYNAMIC1(tcp_context, pointer, pkt) \
{ \
Ip_u16 data = 0; \
Ip_err ret_val = IPCOM_SUCCESS; \
tcp_opt_list tmp_opt_list; \
\
tcp_context->offset_res = (Ip_u8)(tcp_context->offset_res & (~0x0F)); \
tcp_context->offset_res = (Ip_u8)(tcp_context->offset_res | \
(pkt->data[pointer] & 0x0F)); \
\
/* Get c_flags, URP_ZERO, ACK_ZERO, ECN_USED */ \
tcp_context->c_flags = (Ip_u8)(tcp_context->c_flags & (~0xF0)); \
tcp_context->c_flags = (Ip_u8)(tcp_context->c_flags | \
(pkt->data[pointer] & 0xF0)); \
\
/* Get ACK_STRIDE_FLAG */ \
tcp_context->tcp_flags = (Ip_u8)(tcp_context->tcp_flags & (~ACK_STRIDE_IRREG)); \
if (pkt->data[pointer] & 0x40) \
tcp_context->tcp_flags = (Ip_u8)(tcp_context->tcp_flags | ACK_STRIDE_IRREG); \
\
pointer++; \
ipcom_memcpy(&tcp_context->flags, &pkt->data[pointer], 1); \
pointer++; \
/* MSN */ \
ipcom_memcpy(&data, &pkt->data[pointer], 2); \
tcp_context->msn = ipcom_ntohs(data); \
pointer = pointer + 2; \
/* Seq number */ \
ipcom_memcpy(&tcp_context->sn, &pkt->data[pointer], 4); \
pointer = pointer + 4; \
/* Ack number */ \
if(!(tcp_context->c_flags & ACK_ZERO)) \
{ \
ipcom_memcpy(&tcp_context->ackn, &pkt->data[pointer], 4); \
pointer = pointer + 4; \
} \
else tcp_context->ackn = 0; \
/* Window */ \
ipcom_memcpy(&tcp_context->window, &pkt->data[pointer], 2); \
pointer = pointer + 2; \
/* Checksum */ \
ipcom_memcpy(&tcp_context->chksum, &pkt->data[pointer], 2); \
pointer = pointer + 2; \
\
if(!(tcp_context->c_flags & URP_ZERO)) \
{ \
ipcom_memcpy(&tcp_context->uptr, &pkt->data[pointer], 2); \
pointer += 2; \
} else tcp_context->uptr = 0; \
\
if(tcp_context->tcp_flags & ACK_STRIDE_IRREG) \
{ \
ipcom_memcpy(&tcp_context->ackn_stride, &pkt->data[pointer], 2); \
pointer += 2; \
} /* else ack_stride is a static. Leave the previouse value in the context */ \
\
/* Save the older OPT list and recover if the exctraction of the new OPT failes */ \
ipcom_memset(&tmp_opt_list, 0, sizeof(tmp_opt_list)); \
ipcom_list_init(&tmp_opt_list.opt); \
IPROHC_GET_LIST_TCP_OPT(tmp_opt_list, pkt, pointer, ret_val); \
\
if (ret_val == IPCOM_SUCCESS) \
{ \
IPROHC_TCP_D_FREE_OPT_LIST(tcp_context); \
IPROHC_TCP_D_COPY_OPT_LIST(tcp_context, tmp_opt_list); \
} \
else \
{ \
IPROHC_TCP_D_FREE_OPT_LIST1(tmp_opt_list); \
} \
}
/*
*===========================================================================
* IPROHC_FMT_LIST_TCP_OPT
*===========================================================================
* Format TCP options from option list in the context for dynamic chain.
*
* A compressed list of TCP options uses the following encoding:
*
* 0 1 2 3 4 5 6 7
* +---+---+---+---+---+---+---+---+
* | Reserved |PS | m |
* +---+---+---+---+---+---+---+---+
* | XI_1, ..., XI_m | m octets, or m * 4 bits
* / --- --- --- ---/
* | : Padding : if PS = 0 and m is odd
* +---+---+---+---+---+---+---+---+
* | |
* / item_1, ..., item_n / variable
* | |
* +---+---+---+---+---+---+---+---+
*/
#define IPROHC_FMT_LIST_TCP_OPT(tcp_context, pkt, pointer) \
{ \
tcp_item_list *ext, *n_ext; \
Ip_u8 opt, buf[41]; /* Max opt size */ \
int i; \
\
if (tcp_context->opt_num == 0) \
{ \
/* No options. Format the header */ \
pointer--; \
pkt->data[pointer] = 0; \
goto leave; \
} \
\
ipcom_memset(buf, 0, 41); \
for (ext = IPCOM_LIST_LAST(&tcp_context->opt), i = 0; \
ext; \
ext = n_ext, i++) \
{ \
n_ext = IPCOM_LIST_PREV(&ext->item_list); \
opt = ext->index; \
buf[i] = ext->index; \
\
/* Format ITEM chain */ \
if (opt == 1) /* EOL */ \
{ \
pointer--; /* One byte for padding */ \
pkt->data[pointer] = tcp_context->pad_ln; \
/* pointer--; */ \
/* pkt->data[pointer] = ext->item[0]; */ \
} \
else if (opt == 0) /* NOP */ \
{ \
pointer --; \
pkt->data[pointer] = ext->item[0]; \
} \
else \
{ \
pointer = pointer - ext->item_ln; \
ipcom_memcpy(&pkt->data[pointer], ext->item, ext->item_ln); \
} \
} \
\
/* Add padding if needed */ \
if (((tcp_context->opt_num % 2) != 0) && (tcp_context->max_indx <= 7)) \
{ \
pointer --; \
pkt->data[pointer] = (Ip_u8) (0x80 | (buf[0] << 4)); \
i = 1; \
} \
else i = 0; \
\
if (tcp_context->max_indx <= 7) \
{ \
for (i = i; i < tcp_context->opt_num; i++) \
{ \
pointer --; \
pkt->data[pointer] = (Ip_u8)(0x08 | buf[i]); \
i++; \
pkt->data[pointer] = (Ip_u8)(pkt->data[pointer] | 0x80 | (buf[i]<<4)); \
} \
} \
else \
{ \
for (i = i; i < tcp_context->opt_num; i++) \
{ \
/* Format XI chain */ \
pointer--; \
pkt->data[pointer] = (Ip_u8)(0x80 | buf[i]); \
} \
} \
/* Format the header */ \
pointer--; \
pkt->data[pointer] = (Ip_u8)(tcp_context->opt_num & 0x0F); /* Format m */ \
if (tcp_context->max_indx > 7) \
pkt->data[pointer] = pkt->data[pointer] | 0x10; /* ps m */ \
leave: \
pointer = pointer; \
}
/*
*===========================================================================
* IPROHC_GET_LIST_TCP_OPT
*===========================================================================
* Get TCP options from compressed list in dynamic chain.
*
* A compressed list of TCP options uses the following encoding:
*
*
* 0 1 2 3 4 5 6 7
* +---+---+---+---+---+---+---+---+
* | Reserved |PS | m |
* +---+---+---+---+---+---+---+---+
* | XI_1, ..., XI_m | m octets, or m * 4 bits
* / --- --- --- ---/
* | : Padding : if PS = 0 and m is odd
* +---+---+---+---+---+---+---+---+
* | |
* / item_1, ..., item_n / variable
* | |
* +---+---+---+---+---+---+---+---+
*/
#define IPROHC_GET_LIST_TCP_OPT(tmp_opt_list, pkt, pointer, ret_val) \
{ \
tcp_item_list *list_item; \
Ip_u8 ps, item_ln, item_indx, m; \
int i; \
Ip_u8 buf[16]; \
ret_val = IPCOM_SUCCESS; \
\
m = (Ip_u8)(pkt->data[pointer] & 0x0F); \
if (m == 0) \
{ \
pointer++; \
goto leave1; \
} \
ps = (Ip_u8)(pkt->data[pointer] & 0x10); \
pointer++; \
\
if (ps) \
{ \
for(i = 0; i < m; i++) \
{ \
buf[i] = pkt->data[pointer]; \
pointer ++; \
} \
} \
else /* ps is 0, 4 bit items */ \
{ \
for(i = 0; i < m; i++) \
{ \
buf[i] = (Ip_u8)((pkt->data[pointer] & 0xF0) >> 4); \
i++; \
buf[i] = (Ip_u8)(pkt->data[pointer] & 0x0F); \
pointer ++; \
} \
} \
\
for (i = 0; i < m; i++) \
{ \
list_item = ipcom_malloc(sizeof(tcp_item_list)); \
if (list_item == IP_NULL) \
{ \
ipcom_free(list_item); \
IPCOM_LOG0(ERR, "IPROHC_GET_LIST_TCP_OPT, out of memory"); \
ret_val = IPCOM_ERR_NO_MEMORY; \
goto leave1; \
} \
ipcom_memset(list_item, 0, sizeof(tcp_item_list)); \
list_item->irreg_c = 1; \
\
if (ps) /* 8 bit index */ \
{ \
item_indx = list_item->index = (Ip_u8)(buf[i] & 0x0F); \
if(buf[i] & 0x80) \
{ \
if (item_indx == 0) /* NOP */ \
{ \
item_ln = 1; \
list_item->item_ln = 1; \
} \
else if(item_indx == 1) /* EOL */ \
{ \
tmp_opt_list.pad_ln = pkt->data[pointer]; \
item_ln = 1; \
list_item->item_ln = 1; \
} \
else \
{ \
item_ln = list_item->item_ln = pkt->data[pointer + 1]; \
} \
} \
else item_ln = 0; /* No item pressent */ \
} \
else /* 4 bit index */ \
{ \
item_indx = list_item->index = (Ip_u8)(buf[i] & 0x07); \
if(buf[i] & 0x8) \
{ \
if (item_indx == 0) /* NOP */ \
{ \
item_ln = 1; \
list_item->item_ln = 1; \
} \
else if(item_indx == 1) /* EOl */ \
{ \
tmp_opt_list.pad_ln = (Ip_u8)(pkt->data[pointer]); \
item_ln = 1; \
list_item->item_ln = 1; \
} \
else \
{ \
item_ln = list_item->item_ln = pkt->data[pointer + 1]; \
} \
} \
else item_ln = 0; \
} \
\
if (list_item->item_ln != 0) \
{ \
list_item->item = ipcom_malloc(list_item->item_ln); \
if (list_item->item == IP_NULL) \
{ \
ipcom_free(list_item->item); \
ipcom_free(list_item); \
IPCOM_LOG0(ERR, "IPROHC_GET_LIST_TCP_OPT, out of memory"); \
ret_val = IPCOM_ERR_NO_MEMORY; \
goto leave1; \
} \
ipcom_memset(list_item->item, 0, list_item->item_ln); \
\
if (item_indx == 0) /* NOP */ \
list_item->item[0] = 1; \
else if(item_indx == 1) /* EOl */ \
list_item->item[0] = 0; \
else \
ipcom_memcpy(list_item->item, &pkt->data[pointer], list_item->item_ln); \
} \
list_item->irreg_c = 0; /* 0 - list item, 1 irregular chain */ \
ipcom_list_insert_last(&tmp_opt_list.opt, &list_item->item_list); \
pointer = pointer + item_ln; \
} \
leave1: \
pointer = pointer; \
}
/*
*===========================================================================
* IPROHC_UPD_IPID_OFFSET
*===========================================================================
* Loop through IP headers and update ip_id offset: ip_id - sn for each
* IPv4 header.
*/
#ifdef IPCOM_USE_INET
#define IPROHC_UPD_TCP_IPID_OFFSET(ip_context) \
{ \
Iprohc_ip_header *ip_header_; \
\
/* Calcualte IP-ID offset for each IPv4 header : IP-ID - SN */ \
for (ip_header_ = IPCOM_LIST_FIRST(&ip_context->ip_head); \
ip_header_; \
ip_header_ = IPCOM_LIST_NEXT(&ip_header_->ip_list)) \
{ \
if (ip_header_->packet_type == ROHC_PKT_IPV4) \
{ \
/* An IPv4 packet */ \
ip_header_->offset = ipcom_ntohs(ip_header_->header.ip4.id) - \
ip_context->sn; \
} \
} \
}
#else
#define IPROHC_UPD_TCP_IPID_OFFSET(ip_context) IP_NOOP
#endif /* #ifdef IPCOM_USE_INET */
/*
*===========================================================================
* IPROHC_UPD_TCP_STATIC
*===========================================================================
* Update TCP static header
*/
#define IPROHC_UPD_TCP_STATIC(tcp_context, pointer, pkt) \
{ \
IPROHC_GET_TCP_STATIC(tcp_context, pointer, pkt) \
}
/*
*===========================================================================
* IPROHC_UPD_TCP_DYNAMIC
*===========================================================================
* Update TCP dynamic header
*/
#define IPROHC_UPD_TCP_DYNAMIC(tcp_context, pointer, pkt) \
{ \
IPROHC_GET_TCP_DYNAMIC1(tcp_context, pointer, pkt) \
}
/*
*===========================================================================
* IPROHC_RECONSTRUCT_TCP
*===========================================================================
* Reconstruct the packet from TCP context
*/
#define IPROHC_RECONSTRUCT_TCP(tcp_context, pkt) \
{ \
Ip_u8 item_ln, offset; \
int lpointer, i; \
tcp_item_list *opt_list, *n_opt_list; \
\
lpointer = pkt->ipstart; \
/* Reconstruct TCP options */ \
for (opt_list = IPCOM_LIST_LAST(&tcp_context->opt), i = 0; \
opt_list; \
opt_list = n_opt_list, i++) \
{ \
n_opt_list = IPCOM_LIST_PREV(&opt_list->item_list); \
\
if (opt_list->index == 0) /* NOP */ \
item_ln = 1; \
else if(opt_list->index == 1) /* EOP */ \
{ \
item_ln = 1; \
} \
else \
item_ln = opt_list->item_ln; \
\
lpointer = lpointer - item_ln; \
ipcom_memcpy(&pkt->data[lpointer], opt_list->item, item_ln); \
} \
\
/* Add pading if any */ \
if(tcp_context->pad_ln > 0) /* EOP */ \
{ \
lpointer = lpointer - tcp_context->pad_ln; \
ipcom_memset(&pkt->data[lpointer], 0, tcp_context->pad_ln); \
} \
\
/* Reconstruct TCP header fields */ \
offset = (Ip_u8)((tcp_context->payload - lpointer + 20)/4); \
tcp_context->offset_res = (Ip_u8)(tcp_context->offset_res & 0x0F); \
tcp_context->offset_res = (Ip_u8)(tcp_context->offset_res | (offset << 4)); \
\
/* Urgent pointer */ \
lpointer -= 2; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->uptr, 2); \
/* Checksum */ \
lpointer -= 2; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->chksum, 2); \
/* Window */ \
lpointer -= 2; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->window, 2); \
/* flags */ \
lpointer -= 1; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->flags, 1); \
/* Data offset and reserved bits */ \
lpointer -= 1; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->offset_res, 1); \
/* Ack number */ \
lpointer -= 4; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->ackn, 4); \
/* Seq number */ \
lpointer -= 4; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->sn, 4); \
/* Dst port */ \
lpointer -= 2; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->dst_port, 2); \
/* Src port */ \
lpointer -= 2; \
ipcom_memcpy(&pkt->data[lpointer], &tcp_context->src_port, 2); \
\
pkt->ipstart = lpointer; \
}
/*
*===========================================================================
* IPROHC_ACK_FEEDBACK
*===========================================================================
* Process ACK feedback.
*/
#define IPROHC_TCP_ACK_FEEDBACK(context) \
{ \
if (context->state == ROHC_COMP_STATE_IR) \
context->state = ROHC_COMP_STATE_SO; \
\
/* Feedback channel is established */ \
if (context->mode == ROHC_MODE_U) \
context->mode = ROHC_MODE_O; \
}
/*
*===========================================================================
* IPROHC_TCP_PROCESS_FEEDBACK_OPT
*===========================================================================
* Process feedback options.
*/
#define IPROHC_TCP_PROCESS_FEEDBACK_OPT(context, feedback, pointer, size) \
{ \
Ip_u8 opt_type; \
\
while (pointer+1 <= size) \
{ \
opt_type = (feedback[pointer] & 0xF0) >> 4; \
switch (opt_type) \
{ \
case ROHC_FEEDBACK_OPT_REJ: \
/* Set up reject flag in context, not used */ \
context->reject = IP_TRUE; \
pointer ++; \
break; \
case ROHC_FEEDBACK_OPT_SN_NOT_VALID: \
/* Not using SN in feedback currently */ \
pointer ++; \
break; \
case ROHC_FEEDBACK_OPT_SN: \
/* Not using SN in feedback currently */ \
pointer = (Ip_u8)(pointer + 2); \
break; \
case ROHC_FEEDBACK_OPT_CONTEXT_MEMORY: \
/* Not used */ \
pointer ++; \
break; \
default: \
/* Unknown option skip it and continue
parsing next options if any */ \
pointer = (Ip_u8)(pointer + (feedback[pointer] & 0xF) + 1); \
break; \
} \
} \
}
/*
*===========================================================================
* IPROHC_PROCESS_ACKTYPE
*===========================================================================
* Process acktype field from feedback.
*/
#define IPROHC_TCP_PROCESS_ACKTYPE(context, acktype) \
{ \
if (acktype == ROHC_FEEDBACK_ACK) \
{ \
IPROHC_TCP_ACK_FEEDBACK(context); \
} \
else if (acktype == ROHC_FEEDBACK_NACK) \
{ \
context->state = ROHC_COMP_STATE_IR; \
context->pkt_type = ROHC_PKT_IR_DYN; \
} \
else if (acktype == ROHC_FEEDBACK_STATIC_NACK) \
{ \
context->state = ROHC_COMP_STATE_IR; \
context->pkt_type = ROHC_TCP_PKT_IR; \
context->num_ir = 0; \
} \
/* Feedback channel is established */ \
context->mode = ROHC_MODE_O; \
}
/*
*===========================================================================
* IPROHC_TCP_DECOMP_ALLOWED
*===========================================================================
*/
#define IPROHC_TCP_DECOMP_ALLOWED(context, pkt_type, msn) \
{ \
Iprohc_feedback *feedback = IP_NULL; \
\
if (context->state == ROHC_DECOMP_STATE_NO) \
{ \
if (pkt_type != ROHC_TCP_PKT_IR) \
{ \
/* Send STATIC-NACK feedback */ \
feedback = iprohc_tcp_create_feedback_2(context, \
ROHC_FEEDBACK_STATIC_NACK, msn); \
} \
} \
else if (context->state == ROHC_DECOMP_STATE_STATIC) \
{ \
if ((pkt_type != ROHC_TCP_PKT_IR) && \
(pkt_type != ROHC_PKT_IR_DYN) && \
/* General pkts with 7 bit CRC */ \
(pkt_type != ROHC_TCP_PKT_CO) && \
(pkt_type != ROHC_TCP_PKT_RND_8) && \
(pkt_type != ROHC_TCP_PKT_SEQ_8)) \
{ \
/* Send NACK feedback */ \
feedback = iprohc_tcp_create_feedback_2(context, \
ROHC_FEEDBACK_NACK, msn); \
} \
} \
\
if (feedback != IP_NULL) \
{ \
IPROHC_ERROUT(IPCOM_ERR_PERMISSION_DENIED); \
} \
}
/*
*===========================================================================
* IPROHC_TCP_D_MODE_TRANS
*===========================================================================
* Process transition at decompressor
*/
#define IPROHC_TCP_D_MODE_TRANS(d_context, mode) \
{ \
if (d_context->mode == ROHC_MODE_U) \
{ \
/* U-mode-->O-mode */ \
d_context->mode = ROHC_MODE_O; \
d_context->trans = ROHC_DECOMP_TRANS_DONE; \
} \
}
/*
*===========================================================================
* IPROHC_TCP_D_F_STATE_TRANS
*===========================================================================
* Process state transition at decompressor when a decompression fails
*/
#define IPROHC_TCP_D_F_STATE_TRANS(d_context, msn, pkt_type) \
{ \
Ip_u8 ratio; \
\
/* Calculate the failure ratio */ \
ratio = (Ip_u8)((d_context->num_decompressed * 100) % d_context->num_failed); \
\
if (d_context->state == ROHC_DECOMP_STATE_NO) \
{ \
/* Send NACK */ \
(void)iprohc_tcp_create_feedback_2(d_context, \
ROHC_FEEDBACK_STATIC_NACK, msn); \
} \
else if (d_context->state == ROHC_DECOMP_STATE_FULL) \
{ \
if (ratio > IPROHC_D_FULL_RATIO) \
{ \
d_context->state = ROHC_DECOMP_STATE_STATIC; \
\
/* Send NACK */ \
(void)iprohc_tcp_create_feedback_2(d_context, \
ROHC_FEEDBACK_NACK, msn); \
} \
} \
else if (d_context->state == ROHC_DECOMP_STATE_STATIC) \
{ \
if (ratio > IPROHC_D_STATIC_RATIO) \
{ \
if((pkt_type == ROHC_TCP_PKT_IR) || \
(pkt_type == ROHC_PKT_IR_DYN)) \
{ \
d_context->state = ROHC_DECOMP_STATE_NO; \
/* Send NACK */ \
(void)iprohc_tcp_create_feedback_2(d_context, \
ROHC_FEEDBACK_STATIC_NACK, msn); \
} \
else \
/* Send NACK */ \
(void)iprohc_tcp_create_feedback_2(d_context, \
ROHC_FEEDBACK_NACK, msn); \
} \
} \
}
/*
*===========================================================================
* IPROHC_TCP_C_ECN_USED
*===========================================================================
* Determine if ECN is used
*/
#define IPROHC_TCP_C_ECN_USED(tcp_context, ip_context) \
{ \
Ip_u32 flow; \
\
flow = 0; \
if (ip_context->ip_num == 1) \
{ \
base_ip_header = IPCOM_LIST_FIRST(&ip_context->ip_head); \
} \
else /* More then one header */ \
{ \
outer_ip_header = IPCOM_LIST_FIRST(&ip_context->ip_head); \
if(outer_ip_header != IP_NULL) \
base_ip_header = IPCOM_LIST_NEXT(&outer_ip_header->ip_list); \
} \
\
/* Determine the ECN_USED flag */ \
if (base_ip_header != IP_NULL /*!(tcp_context->c_flags & ECN_USED)*/) \
{ \
IPROHC_TCP_C_ECN_USED_IPV4(tcp_context, base_ip_header); \
IPROHC_TCP_C_ECN_USED_IPV6(tcp_context, base_ip_header); \
} \
}
#ifdef IPCOM_USE_INET
#define IPROHC_TCP_C_ECN_USED_IPV4(tcp_context, base_ip_header) \
if (base_ip_header->packet_type == ROHC_PKT_IPV4) \
{ \
/* Is ECN used? */ \
if (base_ip_header->header.ip4.tos & (Ip_u8)0x03) \
tcp_context->c_flags = (Ip_u8)(tcp_context->c_flags | ECN_USED); \
else \
tcp_context->c_flags = (Ip_u8)(tcp_context->c_flags & (~ECN_USED)); \
}
#else
#define IPROHC_TCP_C_ECN_USED_IPV4(tcp_context, base_ip_header) IP_NOOP
#endif
#ifdef IPCOM_USE_INET6
#define IPROHC_TCP_C_ECN_USED_IPV6(tcp_context, base_ip_header) \
if (base_ip_header->packet_type == ROHC_PKT_IPV6) \
{ \
flow = ipcom_ntohl(base_ip_header->header.ip6.ver_class_flow); \
flow = flow >> 20; \
if(flow & 0x03) \
tcp_context->c_flags = (Ip_u8)(tcp_context->c_flags | ECN_USED); \
else \
tcp_context->c_flags = (Ip_u8)(tcp_context->c_flags & (~ECN_USED)); \
}
#else
#define IPROHC_TCP_C_ECN_USED_IPV6(tcp_context, base_ip_header) IP_NOOP
#endif
/*
*
****************************************************************************
* Public TYPES
****************************************************************************
*/
/*
****************************************************************************
* LOCAL TYPES
****************************************************************************
*/
typedef struct tcp_header_struct
{
/* Source port */
Ip_u16 src_port;
/* Destination port */
Ip_u16 dst_port;
/* Sequence number */
Ip_u32 sn;
/* Acknowledgment number */
Ip_u32 ackn;
/* Used to save data_offset, reserved bits */
Ip_u8 offset_res;
/* ECN and other flags */
Ip_u8 flags;
/* Used to save */
/* Window */
Ip_u16 window;
/* Checksum */
Ip_u16 chksum;
/* Urgent pointer */
Ip_u16 uptr;
} tcp_header;
/*
*===========================================================================
* tcp_item_list
*===========================================================================
* This is the TCP reference list structure
*/
typedef struct tcp_item_list_struct
{
Ipcom_list item_list;
Ip_u8 index;
Ip_u8 item_ln;
Ip_u8 irreg_c; /* 1 - Compressed in irregular chain */
Ip_u8 *item;
}tcp_item_list;
typedef struct tcp_opt_list_struct
{
/* TCP options as index/item list */
Ip_u8 item_gen_uindex[GEN_LEN];
Ip_u8 offset_res;
Ip_u8 pad_ln; /* Padding length */
Ip_u8 opt_num;
Ip_u8 max_indx;
Ipcom_list opt; /* tcp_item_list */
}tcp_opt_list;
/*
*===========================================================================
* Iprohc_c_tcp_context_struct
*===========================================================================
* ROHC compression TCP profile specific context structure
* All TCP header fields are in network order
*/
typedef struct Iprohc_c_tcp_context_struct
{
/* All TCP header fields are in network order */
/* Source port */
Ip_u16 src_port;
/* Destination port */
Ip_u16 dst_port;
/* Sequence number */
Ip_u32 sn;
/* Acknowledgment number */
Ip_u32 ackn;
/* Used to save data_offset, reserved bits */
Ip_u8 offset_res;
/* ECN and othe flags */
Ip_u8 flags;
/* Window */
Ip_u16 window;
/* Checksum */
Ip_u16 chksum;
/* Urgent pointer */
Ip_u16 uptr;
int payload; /* Pointer to TCP payload */
int payload_ln; /* Payload Length */
/* Previouse sequence number in host order */
Ip_u32 sn_prev;
/* Previouse acknowledgment number in host order */
Ip_u32 ackn_prev;
/* Controll fileds ecn and msn. Can be updated if 7 bit CRC is used */
/*
* Controll fileds. Can be updated if 7 bit CRC is used.
* 1 - the val is used. O - the val is not used.
* ecn_used;
* ack_zero;
* urp_zero;
* ack_stride_flag;
*/
Ip_u8 c_flags;
Ip_bool scailing_used;
Ip_u32 sec_num_scaled;
Ip_u32 ack_num_scaled;
Ip_u16 ackn_stride;
Ip_u16 msn; /* In host order */
/* IP flags
* Outer IP header
* outer_dscp_irreg;
* outer_ip_ecn_flags_irreg;
* ttl_irregular_chain_flag;
* Inner IP header
* dscp_irreg;
* ttl_hlim_irreg;
* ecn_present;
*/
Ip_u8 ip_flags;
/* TCP header flags
*
* urg_ptr_irreg;
* window_irreg;
* ack_stride_irreg;
* ackn_not_present;
* sn_not_present;
* tcp_res_flags_irreg;
* tcp_ecn_flags_irreg;
*/
Ip_u8 tcp_flags;
/* TCP options index/item list */
Ip_bool list_present;
Ipcom_list list; /* tcp_item_list */
/* Values: 0 - option is not used. 1 - option is used */
Ip_u8 item_gen_uindex[GEN_LEN];
Ip_u8 pad_ln; /* Padding length */
Ip_u8 opt_num;
Ip_u8 max_indx;
#ifdef IPROHC_USE_TEST
#ifdef IPROHC_TCP_IP_SIMULATED_IPID
Ip_u16 simulated_ip_id;
#endif
#endif
Ipcom_list opt; /* tcp_item_list */
}
Iprohc_c_tcp_context;
/*
*===========================================================================
* Iprohc_d_tcp_context_struct
*===========================================================================
* ROHC decompression TCP profile specific context structure
* All TCP header fields are in network order
*/
typedef struct Iprohc_d_tcp_context_struct
{
/* Source port */
Ip_u16 src_port;
/* Destination port */
Ip_u16 dst_port;
/* Sequence number */
Ip_u32 sn;
/* Acknowledgment number */
Ip_u32 ackn;
/* Used to save data_offset, reserved bits */
Ip_u8 offset_res;
/* ECN and othe flags */
Ip_u8 flags;
/* Window */
Ip_u16 window;
/* Checksum */
Ip_u16 chksum;
/* Urgent pointer */
Ip_u16 uptr;
int payload; /* Pointer to TCP payload */
int payload_ln; /* Payload Length */
/*
* Controll fileds. Can be updated if 7 bit CRC is used.
* 1 - the val is used. O - the val is not used.
* ecn_used;
* ack_zero;
* urp_zero;
* ack_stride_flag;
*/
Ip_u8 c_flags;
Ip_u8 tcp_flags;
Ip_bool scailing_used;
Ip_u32 sec_num_scaled;
Ip_u32 ack_num_scaled;
Ip_u16 ackn_stride;
Ip_u16 msn; /* In host order */
/* Values: 0 - option is not used. 1 - option is used */
Ip_u8 item_gen_uindex[GEN_LEN];
/* TCP options as index/item list */
Ip_u8 pad_ln; /* Padding length */
Ip_u8 opt_num;
Ipcom_list opt; /* tcp_item_list */
}
Iprohc_d_tcp_context;
/*
*===========================================================================
* Iprohc_c_tcp_ip_context_struct
*===========================================================================
* ROHC compression TCP_IP profile specific context structure
*/
typedef struct Iprohc_c_tcp_ip_context_struct
{
/* IPvX specific context */
Iprohc_c_ip_context *ip_context;
/* TCP sepecific context */
Iprohc_c_tcp_context *tcp_context;
}
Iprohc_c_tcp_ip_context;
/*
*===========================================================================
* Iprohc_d_tcp_ip_context_struct
*===========================================================================
* ROHC decompression TCP_IP profile specific context structure
*/
typedef struct Iprohc_d_tcp_ip_context_struct
{
/* IPvX specific context */
Iprohc_d_ip_context *ip_context;
/* TCP sepecific context */
Iprohc_d_tcp_context *tcp_context;
}
Iprohc_d_tcp_ip_context;
/*
****************************************************************************
* GLOBAL FUNCTIONS
****************************************************************************
*/
/* Profile registration/deregistration functions */
IP_PUBLIC Ip_err iprohc_profile_tcp_ip_register(void);
IP_PUBLIC Ip_err iprohc_tcp_ip_deregister(void);
/* Profile specific compression functions */
IP_PUBLIC Ip_err
iprohc_tcp_ip_c_find_context(Iprohc_compressor *comp, Ipcom_pkt *pkt,
Iprohc_c_context **c_context);
IP_PUBLIC Iprohc_c_context *
iprohc_tcp_ip_c_create_context(Iprohc_compressor *comp,
Ipcom_pkt *pkt);
IP_PUBLIC Ip_err iprohc_tcp_ip_c_del_context(Iprohc_c_context *context);
IP_PUBLIC Ip_err iprohc_tcp_ip_c_process_feedback(Iprohc_c_context *context,
Ip_u8 *feedback, Ip_u8 size);
IP_PUBLIC Ip_err iprohc_tcp_ip_c_compress(Iprohc_c_context *context,
Ipcom_pkt *pkt);
IP_PUBLIC void iprohc_tcp_ip_c_print_context(Iprohc_c_context *context);
/* Profile specific decompression functions */
IP_PUBLIC Iprohc_d_context *
iprohc_tcp_ip_d_find_context(Iprohc_decompressor *decomp, Ipcom_pkt *pkt);
IP_PUBLIC Iprohc_d_context *
iprohc_tcp_ip_d_create_context(Iprohc_decompressor *decomp,
Ipcom_pkt *pkt);
IP_PUBLIC Ip_err iprohc_tcp_ip_d_del_context(Iprohc_d_context *context);
IP_PUBLIC void iprohc_tcp_ip_d_print_context(Iprohc_d_context *context);
IP_PUBLIC Ip_err iprohc_tcp_ip_d_decompress(Iprohc_d_context *context,
Ipcom_pkt *pkt);
IP_PUBLIC Ip_err
iprohc_c_update_tcp_ip_context(Iprohc_c_context *context,
Ipcom_pkt *pkt, Ip_u8 *pkt_type);
#ifdef __cplusplus
}
#endif
#endif /* #ifndef IPROHC_UDP_IP_H */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/