Files
m241Neelima/components/ip_net2-6.9/iprohc/include/iprohc_parser.h
T
2026-07-30 11:19:44 +05:30

649 lines
21 KiB
C

/* iprohc_parser.h - ROHC parsing head file */
/*
* Copyright (c) 20013 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
--------------------
01h,30jul13,j_y Clean medium impact code review defects
01g,15dec10,ggz Fix for defect WIND00254509
01f,10apr10,ggz Resolve 64bit compiler warnings
01e,20apr09,tlu Fix Linux build warnings for mips64 gcc (cav_ebt5800)
01d,04jul08,tlu Add to handle IP extension headers
01c,11jun08,tlu Fix to parse large CID
01b,14may08,tlu Change function prototyping for parsing pkt types
01a,04apr08,tlu Created.
*/
#ifndef IPROHC_PARSER_H
#define IPROHC_PARSER_H
/*
****************************************************************************
* INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_clib.h>
#include <ipcom_inet.h>
#include <ipcom_cstyle.h>
#include "iprohc_constant.h"
/*
****************************************************************************
* DEFINES
****************************************************************************
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
*===========================================================================
* IPROHC_GET_CID
*===========================================================================
* Get CID from a received compressed packet. pointer will be moved to
* point to Body. type_data will store (type indication + body) octet.
*
* Passed in packet has the following general format:
* RFC 3095, 5.2
*
* --------------------------
* : Add-CID octet : if (CID 1-15) and (small CIDs)
* --------------------------
* | type indication | body |
* --------------------------
* : :
* / 0 - 2 octets of CID / 1 or 2 octets if (large CIDs)
* : :
* --------------------------
* / Body / variable length
* --------------------------
*
*/
#define IPROHC_GET_CID(pkt, pointer, cid, type_data) \
{ \
pointer = pkt->ipstart; \
if ((pkt->data[pointer] >> ROHC_PKT_ADD_CID_SHIFT) == \
ROHC_PKT_ADD_CID) \
{ \
/* small CID */ \
cid = (Ip_u16)(pkt->data[pointer] & 0x0F); \
type_data = pkt->data[pointer+1]; \
pointer += 2; \
} \
else \
{ \
/* large CID */ \
type_data = pkt->data[pointer]; \
\
/* \
* Decode cid according to RFC 3095, 4.5.6. \
* RFC 3095, section 5.2.2: If the first bit is 0, the CID uses \
* one octet. If the first bit is 1, the CID uses two octet. \
*/ \
if ((pkt->data[pointer+1] & 0x80) == 0) \
{ \
cid = pkt->data[pointer+1]; \
pointer += 2; \
} \
else \
{ \
ipcom_memcpy(&cid, &(pkt->data[pointer+1]), 2); \
cid = ip_ntohs(cid); \
cid = (Ip_u16)(cid & 0x7fff); \
pointer += 3; \
} \
} \
}
/*
*===========================================================================
* IPROHC_GET_LIST_ET0
*===========================================================================
* Parse the compressed list encoding type 0
*
* 5.8.6.1 Encoding Type 0 (generic scheme)
*
* ---------------------------------
* | ET=0 |GP|PS| CC = m |
* ---------------------------------
* : gen_id : 1 octet, if GP = 1
* ---------------------------------
* | XI 1, ..., XI m | m octets, or m * 4 bits
* / -----------------/
* | : Padding : if PS = 0 and m is odd
* ---------------------------------
* / item1, ..., item n / variable
* ---------------------------------
*
*/
#define IPROHC_GET_LIST_ET0(ip_head, ptype, pointer, pkt, updated) \
{ \
int i, et_type; \
Iprohc_ref_list *ref_list; \
\
et_type = pkt->data[pointer]; \
ip_head.has_exten = IP_TRUE; \
ip_head.ref_num = (Ip_u8)(et_type & 0x0F); \
ip_head.gen_id = pkt->data[pointer+1]; \
/* move the item pointer to items */ \
if (ip_head.ref_num < 8) \
pointer += 2 + (int)(ip_head.ref_num/2) + (ip_head.ref_num%2); \
else \
pointer += 2 + ip_head.ref_num; \
\
/* create extension header list */ \
for (i = 1; i <= ip_head.ref_num; i++) \
{ \
/* Record the reference list */ \
ref_list = (Iprohc_ref_list *)ipcom_malloc(sizeof(Iprohc_ref_list)); \
if (ref_list == IP_NULL) \
{ \
IPCOM_LOG0(ERR, "IPROHC_GET_LIST_ET0, out of memory(ref_list)"); \
updated = IP_FALSE; \
break; \
} \
\
ipcom_memset(ref_list, 0, sizeof(Iprohc_ref_list)); \
\
/* Add the ref list structure to ROHC IP header structure */ \
ipcom_list_insert_last(&ip_head.ref_head, &ref_list->ref_list); \
\
/* Record the IP extension header */ \
ref_list->type = ptype; \
if (IPROHC_IP6_EXT(ptype)) \
/* \
* IPv6 ext header, Hdr-ext-len (second octet of the ext header) \
* is the length of the extension header in 8-octet units, not \
* including the first 8 octets. \
*/ \
ref_list->length = (Ip_u8)(8 * (pkt->data[pointer+1] + 1)); \
else \
{ \
/* minimal encapsulation header */ \
if (pkt->data[pointer+1] & 0x80) \
ref_list->length = 12; \
else \
ref_list->length = 8; \
} \
\
ip_head.ref_len = (Ip_u16)(ip_head.ref_len + ref_list->length); \
ref_list->data = ipcom_malloc(ref_list->length); \
if (ref_list->data == IP_NULL) \
{ \
IPCOM_LOG0(ERR, "IPROHC_GET_LIST_ET0, out of memory(ref->data)"); \
updated = IP_FALSE; \
break; \
} \
\
/* Make a copy of the ext header */ \
ipcom_memcpy(ref_list->data, &pkt->data[pointer], ref_list->length); \
\
/* Move the pointer to next item */ \
ptype = pkt->data[pointer]; \
pointer += ref_list->length; \
} \
}
/*
*===========================================================================
* IPROHC_UPD_LIST_ET0
*===========================================================================
* Update the compressed list encoding type 0
*
*/
#define IPROHC_UPD_LIST_ET0(iprohc_header, protocol, pointer, pkt) \
{ \
Iprohc_ip_header tmp_ip_header; \
Ip_bool updated = IP_TRUE; \
Ip_u8 proto = protocol; \
\
/* Get the new reference list */ \
ipcom_memset(&tmp_ip_header,0,sizeof(tmp_ip_header)); \
ipcom_list_init(&tmp_ip_header.ref_head); \
IPROHC_GET_LIST_ET0(tmp_ip_header, proto, pointer, pkt, updated); \
if (updated) \
{ \
/* 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 \
{ \
/* Free the new reference list */ \
IPROHC_FREE_REF_LIST((&tmp_ip_header)); \
} \
}
/*
*===========================================================================
* IPROHC_GET_IPV4_STATIC
*===========================================================================
* Get an IPv4 static part in Static chain from a IR packet
*
* 5.7.7.4 IPv4 header static part format
*
* ---------------------------------
* | version = 4 | 0 |
* ---------------------------------
* | Protocol |
* ---------------------------------
* / Source Address / 4 octets
* ---------------------------------
* / Destination Address / 4 octets
* ---------------------------------
*
*/
#ifdef IPCOM_USE_INET
#define IPROHC_GET_IPV4_STATIC(iprohc_header, pointer, pkt) \
{ \
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); \
} \
\
/* 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 += 10; \
}
#else
#define IPROHC_GET_IPV4_STATIC(iprohc_header, pointer, pkt) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_GET_IPV6_STATIC
*===========================================================================
* Get an IPv6 static part in Static chain from a IR packet
*
* 5.7.7.3 IPv6 header static part format
*
* ---------------------------------
* | version = 6 |Flow Label (msb) | 1 octet
* ---------------------------------
* | Flow Label (lsb) | 2 octets
* ---------------------------------
* | Next Header | 1 octet
* ---------------------------------
* / Source Address / 16 octets
* ---------------------------------
* / Destination Address / 16 octets
* ---------------------------------
*
*/
#ifdef IPCOM_USE_INET6
#define IPROHC_GET_IPV6_STATIC(iprohc_header, pointer, pkt) \
{ \
Ipcom_ip6_header *ip6_header = &(iprohc_header->header.ip6); \
Ip_u32 flow = 0, ver_class_flow; \
Ip_u16 flow_lsb; \
\
iprohc_header->packet_type = ROHC_PKT_IPV6; \
/* Form the flow label */ \
flow = (Ip_u32)(pkt->data[pointer] & 0x0F) << 16; \
flow_lsb = ip_ntohs((Ip_u16)pkt->data[pointer+1]); \
flow += flow_lsb; \
\
/* (version=6)+(class will be taken from dynamic part)+flow */ \
/* stored in network order */ \
ver_class_flow = (6<<28) + flow; \
ip6_header->ver_class_flow = ip_htonl(ver_class_flow); \
\
/* next header */ \
ip6_header->nxt = pkt->data[pointer+3]; \
\
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); \
} \
\
/* copy source and destination addresses */ \
ipcom_memcpy(&ip6_header->src, &pkt->data[pointer+4], 16); \
ipcom_memcpy(&ip6_header->dst, &pkt->data[pointer+20], 16); \
\
/* move pointer */ \
pointer += 36; \
}
#else
#define IPROHC_GET_IPV6_STATIC(iprohc_header, pointer, pkt) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_GET_IPV4_DYNAMIC
*===========================================================================
* Get an IPv4 dynamic part in Dynamic chain from a IR/IR-DYN packet
*
* 5.7.7.4 IPv4 header dynamic part format
*
* ---------------------------------
* | Type of Service |
* ---------------------------------
* | Time to Live |
* ---------------------------------
* / Identification / 2 octets
* ---------------------------------
* | DF|RND|NBO|SID| 0 |
* ---------------------------------
* / Generic extension Header list / (not supported)
* ---------------------------------
*
*/
#ifdef IPCOM_USE_INET
#define IPROHC_GET_IPV4_DYNAMIC(iprohc_header, pointer, pkt) \
{ \
Ipcom_ip_header *ip4_header = &(iprohc_header->header.ip4); \
\
ip4_header->tos = pkt->data[pointer]; \
ip4_header->ttl = pkt->data[pointer+1]; \
/* ID is in network order */ \
ipcom_memcpy(&(ip4_header->id), &(pkt->data[pointer+2]), 2); \
iprohc_header->rnd = (Ip_bool)((pkt->data[pointer+4] & 0x40) >> 6); \
iprohc_header->nbo = (Ip_bool)((pkt->data[pointer+4] & 0x20) >> 5); \
iprohc_header->sid = (Ip_bool)((pkt->data[pointer+4] & 0x10) >> 4); \
if (pkt->data[pointer+4] & 0x80) ip4_header->frag |= IPCOM_IPFRAG_DF; \
\
/* Move the pointer */ \
pointer += 5; \
if (iprohc_header->has_exten) \
IPROHC_UPD_LIST_ET0(iprohc_header, ip4_header->protocol, pointer, pkt); \
}
#else
#define IPROHC_GET_IPV4_DYNAMIC(iprohc_header, pointer, pkt) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_GET_IPV6_DYNAMIC
*===========================================================================
* Get an IPv6 dynamic part in Dynamic chain from a IR/IR-DYN packet
*
* 5.7.7.3 IPv6 header dynamic part format
*
* ---------------------------------
* | Traffic Class | 1 octet
* ---------------------------------
* | Hop Limit | 1 octet
* ---------------------------------
* / Generic extension Header list / (not supported)
* ---------------------------------
*
*/
#ifdef IPCOM_USE_INET6
#define IPROHC_GET_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 += (Ip_u32)((pkt->data[pointer])<<20); \
ip6_header->ver_class_flow = ip_htonl(ver_class_flow); \
ip6_header->hlim = pkt->data[pointer+1]; \
\
/* Move pointer */ \
pointer += 2; \
if (iprohc_header->has_exten) \
IPROHC_UPD_LIST_ET0(iprohc_header, ip6_header->nxt, pointer, pkt); \
}
#else
#define IPROHC_GET_IPV6_DYNAMIC(iprohc_header, pointer, pkt) IP_NOOP
#endif
/*
*===========================================================================
* IPROHC_GET_IP_STATIC
*===========================================================================
* Get Static chain in a IR packet
*/
#define IPROHC_GET_IP_STATIC(ip_context, pointer, pkt) \
{ \
Iprohc_ip_header *ip_header_v; \
Ip_u8 protocol; \
\
while (((pkt->data[pointer] >> 4) == 4) || \
((pkt->data[pointer] >> 4) == 6)) \
{ \
ip_header_v = (Iprohc_ip_header *)ipcom_malloc(sizeof(Iprohc_ip_header)); \
if (ip_header_v == IP_NULL) \
{ \
IPCOM_LOG0(ERR,"IPROHC_GET_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] >> 4) == 4) \
{ \
protocol = pkt->data[pointer+1]; \
\
/* An IPv4 header */ \
IPROHC_GET_IPV4_STATIC(ip_header_v, pointer, pkt); \
} \
else \
{ \
protocol = pkt->data[pointer+2]; \
\
/* An IPv6 header */ \
IPROHC_GET_IPV6_STATIC(ip_header_v, pointer, pkt); \
} \
\
if ((protocol != IP_IPPROTO_IPIP) && \
(protocol != IP_IPPROTO_IPV6)) \
break; \
} \
}
/*
*===========================================================================
* IPROHC_GET_IP_DYNAMIC
*===========================================================================
* Get Dynamic chain in a IR/IP-DYN packet
*/
#define IPROHC_GET_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_IPV4_DYNAMIC(ip_header_v, pointer, pkt); \
} \
else \
{ \
/* Get an IPv6 dynamic part */ \
IPROHC_GET_IPV6_DYNAMIC(ip_header_v, pointer, pkt); \
} \
} \
}
/*
*===========================================================================
* IPROHC_UPD_IP_STATIC
*===========================================================================
* Update Static chains from a IR packet
*/
#define IPROHC_UPD_IP_STATIC(ip_context, pointer, pkt) \
{ \
Iprohc_ip_header *ip_header, *p_ip_header; \
\
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 */ \
IPROHC_GET_IPV4_STATIC(ip_header, pointer, pkt); \
} \
else \
{ \
/* Update an IPv6 static part */ \
IPROHC_GET_IPV6_STATIC(ip_header, pointer, pkt); \
} \
} \
}
/*
*===========================================================================
* IPROHC_UPD_IP_DYNAMIC
*===========================================================================
* Update Dynamic chains from a IR/IR-DYN packet
*/
#define IPROHC_UPD_IP_DYNAMIC(ip_context, pointer, pkt) \
IPROHC_GET_IP_DYNAMIC(ip_context, pointer, pkt)
/*
*===========================================================================
* IPROHC_UPD_IP_ADDTIONAL_DYNAMIC
*===========================================================================
* Update additional Dynamic chains from a IP general compressed packet
*/
#define IPROHC_UPD_IP_ADDTIONAL_DYNAMIC(ip_context, pointer, pkt) \
{ \
Iprohc_ip_header *ip_header, *p_ip_header; \
\
/* Skip the first two headers */ \
ip_header = IPCOM_LIST_FIRST(&ip_context->ip_head); \
if(ip_header != IP_NULL) \
ip_header = IPCOM_LIST_NEXT(&ip_header->ip_list); \
if(ip_header != IP_NULL) /* Start for loop from the third IP header */ \
for (ip_header = IPCOM_LIST_NEXT(&ip_header->ip_list); 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) \
{ \
/* Get an IPv4 dynamic part */ \
IPROHC_GET_IPV4_DYNAMIC(ip_header, pointer, pkt); \
} \
else \
{ \
/* Get an IPv6 dynamic part */ \
IPROHC_GET_IPV6_DYNAMIC(ip_header, pointer, pkt); \
} \
} \
}
/*
****************************************************************************
* Public TYPES
****************************************************************************
*/
/*
****************************************************************************
* LOCAL TYPES
****************************************************************************
*/
/*
****************************************************************************
* GLOBAL FUNCTIONS
****************************************************************************
*/
/* Received packet initial parsing functions */
IP_PUBLIC Ip_u8 iprohc_parse_pkt_type(Ipcom_pkt *pkt,
Ip_u16 *feedback_num,
Ip_u8 **feedbacks,
Ipcom_netif *netif);
/* Parse extension */
IP_PUBLIC Ip_err
iprohc_parse_extension(void *out_header, void *in_header,
Ip_u8 *sn, int *mode,
int *in_bno, int *in_rnd,
int *out_bno, int *out_rnd,
Ipcom_pkt *pkt, int *pointer);
#ifdef __cplusplus
}
#endif
#endif /* #ifndef IPROHC_PARSER_H */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/