osmo-ttcn3-hacks/ROHC_CNL113426_LATEST/src/ROHC_EncDec.cc

6768 lines
189 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// //
// Copyright Test Competence Center (TCC) ETH 2003 //
// //
// The copyright to the computer program(s) herein is the property of TCC. //
// The program(s) may be used and/or copied only with the written permission //
// of TCC or in accordance with the terms and conditions stipulated in the //
// agreement/contract under which the program(s) has been supplied. //
// //
///////////////////////////////////////////////////////////////////////////////
//
// File: ROHC_EncDec.cc
// Description: ROHC
// Rev: R3A01
// Prodnr: CNL 113 426
// Updated: 2007-02-07
// Contact: http://ttcn.ericsson.se
//
/* Based on RFC 3095, July 2001 */
#include "IP_Types.hh"
#include "UDP_Types.hh"
#include "RTP_Types.hh"
#include "ROHC_Types.hh"
/* ============ Constants ============ */
/* Encoding and decoding is performed using static buffers */
#define MAX_PACKET_SIZE 1500
#define HEXDUMP_BUFFER_SIZE 1500
/* ROHC mode constants */
#define ROHC_mode_C 0
#define ROHC_mode_U 1
#define ROHC_mode_O 2
#define ROHC_mode_R 3
/* Inner and outer IP level numbers */
#define Inner_IP 1
#define Outer_IP 0
/* ============ Utilities ============ */
#define isIR(val) (((val) & 0xFE) == 0xFC)
#define isIRDYN(val) ((val) == 0xF8)
#define isUOR2(val) (((val) & 0xE0) == 0xC0)
/* Shifts the passed bit value from the position 0 to position N. */
#define ShiftUpBit(val, position) ((val) << (position)) & (0x01 << (position))
/* Shifts the passed bit value from the position N to position 0. */
#define ShiftDownBit(val, position) (((val) >> (position)) & 0x01)
/* Logs an event, when the 'value' field in the type 'typename' is not
implemented. 'typename' must be provided in '"'s */
#define Log_not_implemented_union_field(typename, value) \
TTCN_error("Encoding of the selected union field (%u) in type " \
typename " is not implemented", (value));
/* Prints a hexdump of the buffer 'buf' in length 'length'. */
#define Log_hexdump(buf, length) \
TTCN_logger.log(TTCN_DEBUG, "Buffer (length = %d):\n%s", \
(length), debug_hexdump((buf), debug_buf, (length)));
/* Logs the name of the function on entering */
#define Log_function_name_on_enter() \
TTCN_logger.log(TTCN_DEBUG, "Entering %s", __FUNCTION__);
/* Logs the name of the function on leaving */
#define Log_function_name_on_leave() \
TTCN_logger.log(TTCN_DEBUG, "Leaving %s", __FUNCTION__);
/* Logs an object */
#define Log_object(o) \
TTCN_logger.begin_event(TTCN_DEBUG); \
(o).log(); \
TTCN_logger.end_event(); \
//**********************************************************
// NAMESPACE
//**********************************************************
namespace ROHC__Types {
using namespace General__Types;
using namespace IP__Types;
using namespace UDP__Types;
using namespace RTP__Types;
/* Umbrella type for parsing an incoming ROHC packet */
typedef struct
{
ROHC__context & context;
int cid;
int compressed_ah_data_len[2];
bool ipx_gre_cksum_present[2];
} t_dat;
/* TODO: this is not a thread-safe thing to do. For FT, it does not
matter, but the buffer should be allocated dynamically. */
static char debug_buf[HEXDUMP_BUFFER_SIZE];
static char *
debug_hexdump(const unsigned char *src_buf, char *dest_buf, unsigned int len)
{
unsigned int offset = 0;
char val;
memset(dest_buf, 0, HEXDUMP_BUFFER_SIZE);
if (src_buf == NULL || len == 0)
return dest_buf;
for (unsigned int i = 0; i < len; i++)
{
if ((i % 16) == 0 && i > 0)
{
dest_buf[offset] = 0x0A; /* newline after each line */
offset++;
}
if ((i % 8) == 0)
{
dest_buf[offset] = 0x20; /* space after 8 characters */
offset++;
}
val = (src_buf[i] >> 4) & 0x0F; /* First digit */
val = (val < 10) ? (val + 48) : (val + 65 - 10);
dest_buf[offset] = val;
offset++;
val = src_buf[i] & 0x0F; /* Second digit */
val = (val < 10) ? (val + 48) : (val + 65 - 10);
dest_buf[offset] += val;
offset++;
dest_buf[offset] = 0x20; /* space after the value */
offset++;
}
return dest_buf;
}
/* ============ Consistency check routines ============ */
void
Check_field_value(char *text, int urherenow, int wannabe)
{
if (wannabe != urherenow)
{
TTCN_logger.log(TTCN_WARNING, "Field '%s' must be %u, %u is given",
text, wannabe, urherenow);
}
}
void
Check_field_presence(char *text, bool flag, bool presence)
{
if (flag && !presence)
{
TTCN_logger.log(TTCN_WARNING, "Field '%s' must be present, when "
"its presence flag is set", text);
}
else if (!flag && presence)
{
TTCN_logger.log(TTCN_WARNING, "Field '%s' must not be present, when "
"its presence flag is unset", text);
}
}
void
Check_feedback_code__size(const INT3b & code, const OPTIONAL < LIN1 > &size)
{
if (size.ispresent() && code > 0)
{
TTCN_logger.log(TTCN_WARNING,
"Code field must be 0, when size field is specified");
}
}
void
Check_feedback_optlen__optsize(const INT4b & len,
const OPTIONAL < OCTETSTRING > &data)
{
if (data.ispresent() && (data().lengthof() != len))
{
int flen = len;
int fdatalen = data().lengthof();
TTCN_logger.log(TTCN_WARNING,
"Feedback option length (%u) is different from "
"the length of feedback option data (%u)", flen, fdatalen);
}
else if (!data.ispresent() && len > 0)
{
int flen = len;
TTCN_logger.log(TTCN_WARNING,
"No feedback option data, but feedback option length "
"is not 0 (%u)", flen);
}
}
void
Check_ps_bit__xi_format(const BIT1 & psbit,
const OPTIONAL < XI__list > &xilist)
{
if (!xilist.ispresent())
return;
if (xilist().get_selection() == XI__list::ALT_xi__item8 && (*psbit) == 0)
{
TTCN_logger.log(TTCN_WARNING, "PS bit is 0, 4-bit indices must be used");
}
else if (xilist().get_selection() == XI__list::ALT_xi__item4 && (*psbit) == 1)
{
TTCN_logger.log(TTCN_WARNING, "PS bit is 1, 8-bit indices must be used");
}
}
INTEGER
ComputeCRC(const unsigned char *buf, int length, int crclen)
{
int crcval, poly, shiftmask;
Log_function_name_on_enter();
TTCN_logger.log(TTCN_DEBUG, "Calculating CRC-%d over:", crclen);
Log_hexdump(buf, length);
switch (crclen)
{
case 3:
poly = 0x06;
crcval = 0x07;
shiftmask = 0x03;
break;
case 7:
poly = 0x79;
crcval = 0x7F;
shiftmask = 0x3F;
break;
case 8:
poly = 0xE0;
crcval = 0xFF;
shiftmask = 0x7F;
break;
case 32:
poly = 0xEDB88320;
crcval = 0xFFFFFFFF;
shiftmask = 0x7FFFFFFF;
break;
default:
poly = 0;
TTCN_error("Unknown CRC length(%d)\n", crclen);
break;
}
if (poly == 0)
return 0;
for (int i = 0; i < length; i++)
{
for (int j = 0; j < 8; j++)
{
if ((crcval & 0x01) ^ (ShiftDownBit(buf[i], j)))
{
crcval = (crcval >> 1) & shiftmask;
crcval ^= poly;
}
else
{
crcval = (crcval >> 1) & shiftmask;
}
}
}
/* CRC-32 in ROHC needs to be negated at the end */
if (crclen == 32)
{
crcval ^= 0xffffffff;
}
Log_function_name_on_leave();
unsigned int ui = (unsigned int)crcval;
char sbuf[16];
sprintf(sbuf, "%u", ui);
return INTEGER(sbuf);
}
/* ============ Encoding functions for base types ============ */
/** Returns the index of the innermost IP level, based on the number of
IP levels in the context. */
int
getInnermostIPidx(t_dat *dat)
{
// More than 1 levels: the innermost is always the index = 1
if (dat->context.ip__ctx().size_of() > 1)
return Inner_IP;
else
// The index is the one and only 0.
return Outer_IP;
}
/* Returns the index of the inner or outer IP level in the context, based on the
number of the IP levels in the context. If the return value is negative,
it indicates that the outer IP level does not exists. Negative value is
never returned, if the ip_level is the Inner IP level. */
int
getIPidx(t_dat *dat, int ip_level)
{
if (ip_level == Outer_IP)
{
if (dat->context.ip__ctx().size_of() > 1)
return Outer_IP;
else
return -1;
}
else if (ip_level == Inner_IP)
return getInnermostIPidx(dat);
else
return ip_level;
}
/** Initializes the context of the specified IP level. */
void
initIPcontext(t_dat *dat, int ip_level, int ip_version)
{
unsigned char ctemp = 0;
IP__context & field = dat->context.ip__ctx()[ip_level];
Log_function_name_on_enter();
field.version() = INTEGER(ip_version);
if (! field.rnd__bit().is_bound()) field.rnd__bit() = BOOLEAN(ctemp);
if (! field.ah__present().is_bound()) field.ah__present() = BOOLEAN(ctemp);
if (! field.gre__present().is_bound()) field.gre__present() = BOOLEAN(ctemp);
if (! field.esp__present().is_bound()) field.esp__present() = BOOLEAN(ctemp);
if (! field.ah__data__len().is_bound())
field.ah__data__len() = INTEGER(ctemp);
if (! field.gre__cksum__present().is_bound())
field.gre__cksum__present() = BOOLEAN(ctemp);
Log_object(dat->context);
Log_function_name_on_leave();
}
/** Initializes the UDP context. */
void
initUDPcontext(t_dat *dat)
{
unsigned char ctemp = 1;
UDP__context & field = dat->context.udp__ctx();
if (! field.udp__cksum().is_bound()) field.udp__cksum() = BOOLEAN(ctemp);
}
/** Initializes the specified CID's context. */
void
initCIDcontext(t_dat *dat)
{
unsigned char ctemp = 0;
ROHC__context & field = dat->context;
if (! field.mode().is_bound()) field.mode() = INTEGER(cg__ROHC__mode__U);
if (! field.profile().is_bound()) field.profile() = INTEGER(ctemp);
if (! field.pkt().is_bound()) field.pkt() = Packet__type(Packet__type::IR);
if (! field.ip__ctx().is_bound()) initIPcontext(dat, 0, 4);
initUDPcontext(dat);
}
/** Initializes the umbrella type before the ROHC packet parsing starts. */
t_dat
initTDAT(ROHC__config & config, int cid)
{
t_dat dat = { config.context()[cid], cid, {0, 0}, {false, false} };
// Expect AH auth data and GRE checksum after the compressed header
// by default. If the uncompressed form is used, these values will be
// set to 0 or false during parsing.
dat.compressed_ah_data_len[0] =
config.context()[cid].ip__ctx()[0].ah__data__len();
dat.ipx_gre_cksum_present[0] =
config.context()[cid].ip__ctx()[0].gre__cksum__present();
if (config.context()[cid].ip__ctx().size_of() > 1)
{
dat.compressed_ah_data_len[1] =
config.context()[cid].ip__ctx()[1].ah__data__len();
dat.ipx_gre_cksum_present[1] =
config.context()[cid].ip__ctx()[1].gre__cksum__present();
}
return dat;
}
/** Returns, whether there is any compressed IPv4 level,
where the RND bit is 0. */
bool
isAnyIPv4RNDunset(t_dat *dat)
{
for (int i = 0; i < 2; i++)
{
int ip_idx = getIPidx(dat, i);
if (ip_idx >= 0) // IP level exists
{
if (! dat->context.ip__ctx()[ip_idx].rnd__bit())
return true;
}
}
return false;
}
/* Encodes an OCTETSTING value */
int
Set_octetstring(unsigned char *buf, const OCTETSTRING & val)
{
memcpy(&(buf[0]), val, val.lengthof());
return val.lengthof();
}
/* Encodes a LIN2_BO_LAST value */
int
Set_LIN2_BO_LAST(unsigned char *buf, const LIN2__BO__LAST & val)
{
buf[0] = (val >> 8) & 0xFF;
buf[1] = val & 0xFF;
return 2;
}
/* Encodes a LIN4_BO_LAST value */
int
Set_LIN4_BO_LAST(unsigned char *buf, const LIN4__BO__LAST & val)
{
buf[0] = (val >> 24) & 0xFF;
buf[1] = (val >> 16) & 0xFF;
buf[2] = (val >> 8) & 0xFF;
buf[3] = val & 0xFF;
return 4;
}
/* Encodes a LIN1 value */
int
Set_LIN1(unsigned char *buf, const LIN1 & val)
{
buf[0] = val & 0xFF;
return 1;
}
/* Returns the length of the SDVL encoded CID value 'val'. If the value
is invalid, exits via the ttcn_error(). */
int
SDVL_encoded_CID_length(int val)
{
if (val <= 0x7F)
return 1;
else if (val <= 0x3FFF)
return 2;
else if (val <= 0x1FFFFF)
return 3;
else if (val <= 0x1FFFFFFF)
return 4;
else
TTCN_error("Value %u is too big for the SDVL encoder "
"(at most 29 bits can be used)", val);
return 0;
}
int
Set_SDVL_field(unsigned char *buf, const INTEGER & val, int encoded_length)
{
int len = 0;
Log_function_name_on_enter();
if ((val <= 0x7F && encoded_length == 0) || encoded_length == 1)
{
buf[len] = val & 0x7F;
len += 1;
}
else if ((val <= 0x3FFF && encoded_length == 0) || encoded_length == 2)
{
buf[len] = 0x80 | ((val >> 8) & 0x7F);
len += 1;
buf[len] = val & 0xFF;
len += 1;
}
else if ((val <= 0x1FFFFF && encoded_length == 0) || encoded_length == 3)
{
buf[len] = 0xC0 | ((val >> 16) & 0x3F);
len += 1;
buf[len] = (val >> 8) & 0xFF;
len += 1;
buf[len] = val & 0xFF;
len += 1;
}
else if ((val <= 0x1FFFFFFF && encoded_length == 0) || encoded_length == 4)
{
buf[len] = 0xE0 | ((val >> 24) & 0x1F);
len += 1;
buf[len] = (val >> 16) & 0xFF;
len += 1;
buf[len] = (val >> 8) & 0xFF;
len += 1;
buf[len] = val & 0xFF;
len += 1;
}
else
{
int tmp = val;
TTCN_error("Value %u (specified length is %u) is too big for the "
"SDVL encoder (at most 29 bits can be used)",
tmp, encoded_length);
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
/* ============ Encoding wrappers for optional base types ============ */
/* Encodes an optional OCTETSTING value */
int
Set_octetstring_opt(unsigned char *buf, const OPTIONAL < OCTETSTRING > &val)
{
if (!val.ispresent())
return 0;
return Set_octetstring(buf, val());
}
/* Encodes an optional LIN2_BO_LAST value */
int
Set_LIN2_BO_LAST_opt(unsigned char *buf,
const OPTIONAL < LIN2__BO__LAST > &val)
{
if (!val.ispresent())
return 0;
return Set_LIN2_BO_LAST(buf, val());
}
/* Encodes an optional LIN4_BO_LAST value */
int
Set_LIN4_BO_LAST_opt(unsigned char *buf,
const OPTIONAL < LIN4__BO__LAST > &val)
{
if (!val.ispresent())
return 0;
return Set_LIN4_BO_LAST(buf, val());
}
/* Encodes an optional LIN1 value */
int
Set_LIN1_opt(unsigned char *buf, const OPTIONAL < LIN1 > &val)
{
if (!val.ispresent())
return 0;
return Set_LIN1(buf, val());
}
int
Set_SDVL_field_opt(unsigned char *buf,
const OPTIONAL < INTEGER > &val, int length)
{
int len = 0;
Log_function_name_on_enter();
if (!val.ispresent())
return 0;
len += Set_SDVL_field(buf, val(), length);
Log_function_name_on_leave();
return len;
}
/* ============ Encoding functions for common ROHC types ============ */
int
Set_CID(unsigned char *buf, const INTEGER & cid, BOOLEAN const &large_cid)
{
int len = 0;
Log_function_name_on_enter();
if (large_cid == false)
{
if (cid > 0)
{
buf[len] = 0xE0 + (cid & 0x0F);
len += 1;
}
}
else
len += Set_SDVL_field(&buf[len], cid, 0);
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
/* CSRC and IP extension header item list encoding */
int
Set_Item_list_opt(unsigned char *buf, const OPTIONAL < Item__list > &item_list)
{
int len = 0;
Log_function_name_on_enter();
if (!item_list.ispresent())
{
Log_function_name_on_leave();
return len;
}
/* Item list is an IP extension header list */
if (item_list().get_selection() == Item__list::ALT_ip__item__list)
{
IP__Item__list ip_item_list = item_list().ip__item__list();
for (int num = 0; num < ip_item_list.size_of(); num++)
{
int start_pos = len;
switch (ip_item_list[num].get_selection())
{
case Item::ALT_ipv6__ext__item:
{
IPv6__ext__item & item = ip_item_list[num].ipv6__ext__item();
len += Set_LIN1(&buf[len], item.nexthead());
/* Length of the header in 8-octet units, not including
the first 8 octets. */
if (item.hdr__ext__len() == 0)
{
if ((item.data().lengthof() + 2) % 8 != 0)
{
TTCN_error("Invalid length (%u) of the IPv6 extension header",
item.data().lengthof());
}
buf[len] = (item.data().lengthof() + 2) / 8 - 1;
len += 1;
}
else
len += Set_LIN1(&buf[len], item.hdr__ext__len());
len += Set_octetstring(&buf[len], item.data());
break;
}
case Item::ALT_mine__item:
{
MINE__item & item = ip_item_list[num].mine__item();
Check_field_value("MINE protocol", item.protocol(), c__ip__proto__mine);
Check_field_value("MINE reserved", *item.reserved(), 0);
len += Set_LIN1(&buf[len], item.protocol());
buf[len] = (*item.s__bit()) << 7;
buf[len] += *item.reserved();
len += 1;
len += Set_LIN2_BO_LAST(&buf[len], item.cksum());
len += Set_octetstring(&buf[len], item.dstaddr());
len += Set_octetstring_opt(&buf[len], item.srcaddr());
break;
}
case Item::ALT_ah__item:
{
AH__item & item = ip_item_list[num].ah__item();
Check_field_value("AH nexthead", item.nexthead(), c__ip__proto__ah);
len += Set_LIN1(&buf[len], item.nexthead());
/* RFC 2402: This 8-bit field specifies the length of AH in
32-bit words (4-byte units), minus "2". */
if (item.payload__len() == 0)
{
if (item.auth__data().ispresent())
buf[len] = (item.auth__data()().lengthof() / 4) + 3 - 2;
else
buf[len] = 1;
len += 1;
}
else
len += Set_LIN1(&buf[len], item.payload__len());
Check_field_value("AH reserved", item.reserved(), 0);
len += Set_LIN2_BO_LAST(&buf[len], item.reserved());
len += Set_LIN4_BO_LAST(&buf[len], item.spi());
len += Set_LIN4_BO_LAST(&buf[len], item.sn());
len += Set_octetstring_opt(&buf[len], item.auth__data());
break;
}
case Item::ALT_esp__item:
{
ESP__item & item = ip_item_list[num].esp__item();
Check_field_value("ESP nexthead", item.nexthead(), c__ip__proto__esp);
len += Set_LIN1(&buf[len], item.nexthead());
len += Set_LIN4_BO_LAST(&buf[len], item.spi());
len += Set_LIN4_BO_LAST(&buf[len], item.sn());
break;
}
case Item::ALT_gre__item:
{
GRE__item & item = ip_item_list[num].gre__item();
Check_field_value("GRE nexthead", item.nexthead(), c__ip__proto__gre2);
len += Set_LIN1(&buf[len], item.nexthead());
buf[len] = (*item.C__bit()) << 7;
Check_field_value("GRE reserved1", (int) *item.reserved__1(), 0);
buf[len] += (*item.reserved__1()) << 6;
buf[len] += (*item.K__bit()) << 5;
buf[len] += (*item.S__bit()) << 4;
Check_field_value("GRE reserved2", (int) *item.reserved__2(), 0);
buf[len] += (*item.reserved__2()) << 3;
buf[len] += *item.version();
len += 1;
Check_field_presence("checksum", *item.C__bit() == 1,
item.cksum().ispresent());
Check_field_presence("key", *item.K__bit() == 1,
item.key().ispresent());
Check_field_presence("sn", *item.S__bit() == 1,
item.sn().ispresent());
len += Set_LIN2_BO_LAST_opt(&buf[len], item.cksum());
len += Set_LIN4_BO_LAST_opt(&buf[len], item.key());
len += Set_LIN4_BO_LAST_opt(&buf[len], item.sn());
break;
}
default:
{
Log_not_implemented_union_field("Item",
ip_item_list[num].get_selection());
break;
}
}
TTCN_logger.log(TTCN_DEBUG, "%uth item:", num);
Log_hexdump(&(buf[start_pos]), len - start_pos);
}
}
else if (item_list().get_selection() == Item__list::ALT_csrc__item__list)
{
/* Item list is CSRC item list */
for (int num = 0; num < item_list().csrc__item__list().size_of(); num++)
{
int start_pos = len;
len += Set_octetstring( &buf[len],
item_list().csrc__item__list()[num] );
TTCN_logger.log(TTCN_DEBUG, "%uth item:", num);
Log_hexdump(&(buf[start_pos]), len - start_pos);
}
}
else if (item_list().get_selection() == Item__list::ALT_raw__data)
{
/* Item list is a raw octetstring */
for (int num = 0; num < item_list().csrc__item__list().size_of(); num++)
{
int start_pos = len;
len += Set_octetstring(&buf[len], item_list().raw__data()[num] );
TTCN_logger.log(TTCN_DEBUG, "%uth item:", num);
Log_hexdump(&(buf[start_pos]), len - start_pos);
}
}
else
{
Log_not_implemented_union_field("Item_list", item_list().get_selection());
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_XI_list_opt(unsigned char *buf, const OPTIONAL < XI__list > &xilist,
const OPTIONAL < BITSTRING > &padding, int length)
{
int len = 0;
int halfbyte = 0;
Log_function_name_on_enter();
if (!xilist.ispresent())
{
Log_function_name_on_leave();
return len;
}
switch (xilist().get_selection())
{
case XI__list::ALT_xi__item4:
{
if (length != xilist().xi__item4().size_of())
TTCN_logger.log(TTCN_WARNING,
"Number of indices != value of CC field");
for (int num = 0; num < xilist().xi__item4().size_of(); num++)
{
if (halfbyte)
{
buf[len] += ((*xilist().xi__item4()[num].x__ind()) << 3) & 0x08;
buf[len] += xilist().xi__item4()[num].index() & 0x07;
len += 1;
}
else
{
buf[len] = ((*xilist().xi__item4()[num].x__ind()) << 7) & 0x80;
buf[len] += (xilist().xi__item4()[num].index() << 4) & 0x70;
}
halfbyte = 1 - halfbyte; // Invert the value (0 -> 1 or 1 -> 0)
}
break;
}
case XI__list::ALT_xi__item8:
{
if (length != xilist().xi__item8().size_of())
TTCN_logger.log(TTCN_WARNING,
"Number of indices != value of CC field");
for (int num = 0; num < xilist().xi__item8().size_of(); num++)
{
buf[len] = ((*xilist().xi__item8()[num].x__ind()) << 7) & 0x80;
buf[len] += xilist().xi__item8()[num].index() & 0x7F;
len += 1;
}
break;
}
default:
Log_not_implemented_union_field("XI_list", xilist().get_selection());
break;
}
if (padding.ispresent() && halfbyte == 0)
{
TTCN_logger.log(TTCN_WARNING, "Specified padding is ignored");
}
else if (!padding.ispresent() && halfbyte)
{
TTCN_logger.log(TTCN_WARNING,
"Padding not specified, padding bits left uninitialized");
}
else if (padding.ispresent())
{
Check_field_value("Index padding", *padding(), 0);
buf[len] += (*padding()) & 0x0F;
len += 1;
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Encoding_Type_0(unsigned char *buf, const Enc__Type__0 & enct0)
{
int len = 0;
Log_function_name_on_enter();
Check_field_presence("gen_id", *enct0.gp__bit() == 1,
enct0.gen__id().ispresent());
Check_field_value("Encoding type", *enct0.et(), 0);
buf[len] = ((*enct0.et()) << 6) & 0xC0;
buf[len] += ShiftUpBit(*enct0.gp__bit(), 5);
buf[len] += ShiftUpBit(*enct0.ps__bit(), 4);
buf[len] += enct0.cc() & 0x0F;
len += 1;
len += Set_LIN1_opt(&buf[len], enct0.gen__id());
Check_ps_bit__xi_format(enct0.ps__bit(), enct0.xi__list());
len += Set_XI_list_opt(&buf[len], enct0.xi__list(), enct0.padding(),
enct0.cc());
len += Set_Item_list_opt(&buf[len], enct0.item__list());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Encoding_Type_1(unsigned char *buf, const Enc__Type__1 & enct1)
{
int len = 0;
int n = 0;
Log_function_name_on_enter();
Check_field_presence("gen_id", *enct1.gp__bit() == 1,
enct1.gen__id().ispresent());
Check_field_value("Encoding type", *enct1.et(), 1);
buf[len] = ((*enct1.et()) << 6) & 0xC0;
buf[len] += ShiftUpBit(*enct1.gp__bit(), 5);
buf[len] += ShiftUpBit(*enct1.ps__bit(), 4);
buf[len] += enct1.xi1() & 0x0F;
len += 1;
len += Set_LIN1_opt(&buf[len], enct1.gen__id());
len += Set_LIN1_opt(&buf[len], enct1.ref__id());
len += Set_octetstring(&buf[len], enct1.insbitmask());
// Count the number of 1's in the bitmask
for (int i = 0; i < enct1.insbitmask().lengthof(); ++i)
{
if (enct1.insbitmask() & int2oct(i + 1, enct1.insbitmask().lengthof()))
++n;
}
Check_ps_bit__xi_format(enct1.ps__bit(), enct1.xi__list());
len += Set_XI_list_opt(&buf[len], enct1.xi__list(), enct1.padding(), n);
len += Set_Item_list_opt(&buf[len], enct1.item__list());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Encoding_Type_2(unsigned char *buf, const Enc__Type__2 & enct2)
{
int len = 0;
Check_field_presence("gen_id", *enct2.gp__bit() == 1,
enct2.gen__id().ispresent());
Check_field_value("Encoding type", *enct2.et(), 2);
buf[len] = ((*enct2.et()) << 6) & 0xC0;
buf[len] += ShiftUpBit(*enct2.gp__bit(), 5);
buf[len] += ShiftUpBit(*enct2.res(), 4);
buf[len] += enct2.count() & 0x0F;
len += 1;
len += Set_LIN1_opt(&buf[len], enct2.gen__id());
len += Set_LIN1_opt(&buf[len], enct2.ref__id());
len += Set_octetstring(&buf[len], enct2.rembitmask());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Encoding_Type_3(unsigned char *buf, const Enc__Type__3 & enct3)
{
int len = 0;
int n = 0;
Check_field_presence("gen_id", *enct3.gp__bit() == 1,
enct3.gen__id().ispresent());
Check_field_value("Encoding type", *enct3.et(), 3);
buf[len] = ((*enct3.et()) << 6) & 0xC0;
buf[len] += ShiftUpBit(*enct3.gp__bit(), 5);
buf[len] += ShiftUpBit(*enct3.ps__bit(), 4);
buf[len] += enct3.xi1() & 0x0F;
len += 1;
len += Set_LIN1_opt(&buf[len], enct3.gen__id());
len += Set_LIN1_opt(&buf[len], enct3.ref__id());
len += Set_octetstring(&buf[len], enct3.rembitmask());
len += Set_octetstring(&buf[len], enct3.insbitmask());
// Count the number of 1's in the bitmask
for (int i = 0; i < enct3.insbitmask().lengthof(); ++i)
{
if (enct3.insbitmask() & int2oct(i + 1, enct3.insbitmask().lengthof()))
++n;
}
Check_ps_bit__xi_format(enct3.ps__bit(), enct3.xi__list());
len += Set_XI_list_opt(&buf[len], enct3.xi__list(), enct3.padding(), n);
len += Set_Item_list_opt(&buf[len], enct3.item__list());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Compr_head_list_opt(unsigned char *buf,
const OPTIONAL < Compr__head__list > &chl)
{
int len = 0;
Log_function_name_on_enter();
if (!chl.ispresent())
{
Log_function_name_on_leave();
return len;
}
if (chl().get_selection() == Compr__head__list::ALT_enctype0)
len += Set_Encoding_Type_0(&buf[len], chl().enctype0());
else if (chl().get_selection() == Compr__head__list::ALT_enctype1)
len += Set_Encoding_Type_1(&buf[len], chl().enctype1());
else if (chl().get_selection() == Compr__head__list::ALT_enctype2)
len += Set_Encoding_Type_2(&buf[len], chl().enctype2());
else if (chl().get_selection() == Compr__head__list::ALT_enctype3)
len += Set_Encoding_Type_3(&buf[len], chl().enctype3());
else
{
Log_not_implemented_union_field("Compr_head_list", chl().get_selection());
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_AEGSeqnum_opt(unsigned char *buf, const OPTIONAL < AEGSeqnum > &oseqn)
{
int len = 0;
Log_function_name_on_enter();
if (!oseqn.ispresent())
{
Log_function_name_on_leave();
return len;
}
if (oseqn().get_selection() == AEGSeqnum::ALT_short__form)
{
Check_field_value("form-bit", (int) *oseqn().short__form().ind(), 0);
buf[len] = ShiftUpBit(*oseqn().short__form().ind(), 7);
buf[len] += oseqn().short__form().lsb__of__seqnum() & 0x7F;
len += 1;
}
else if (oseqn().get_selection() == AEGSeqnum::ALT_long__form)
{
Check_field_value("form-bit", (int) *oseqn().long__form().ind(), 1);
buf[len] = ShiftUpBit(*oseqn().long__form().ind(), 7);
buf[len] += (oseqn().long__form().lsb__of__seqnum() >> 24) & 0x7F;
len += 1;
buf[len] = (oseqn().long__form().lsb__of__seqnum() >> 16) & 0xFF;
len += 1;
buf[len] = (oseqn().long__form().lsb__of__seqnum() >> 8) & 0xFF;
len += 1;
buf[len] = oseqn().long__form().lsb__of__seqnum() & 0xFF;
len += 1;
}
else
Log_not_implemented_union_field("AEGSeqnum", oseqn().get_selection());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_IPv4_static_chain(unsigned char *buf, const IPv4__Static & chain)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("IPv4 version", chain.version(), 4);
buf[len] = (chain.version() << 4) & 0xF0;
Check_field_value("IPv4 reserved (static chain)", chain.reserved(), 0);
buf[len] += chain.reserved() & 0x0F;
len += 1;
len += Set_LIN1(&buf[len], chain.proto());
len += Set_octetstring(&buf[len], chain.srcaddr());
len += Set_octetstring(&buf[len], chain.dstaddr());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_IPv6_static_chain(unsigned char *buf, const IPv6__Static & chain)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("IPv6 version", chain.version(), 6);
buf[len] = (chain.version() << 4) & 0xF0;
buf[len] += (chain.flowlabel() >> 16) & 0x0F;
len += 1;
buf[len] = (chain.flowlabel() >> 8) & 0xFF;
len += 1;
buf[len] = chain.flowlabel() & 0xFF;
len += 1;
len += Set_LIN1(&buf[len], chain.nexthead());
len += Set_octetstring(&buf[len], chain.srcaddr());
len += Set_octetstring(&buf[len], chain.dstaddr());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_UDP_static_chain(unsigned char *buf, const UDP__Static & chain)
{
int len = 0;
Log_function_name_on_enter();
len += Set_LIN2_BO_LAST(&buf[len], chain.srcport());
len += Set_LIN2_BO_LAST(&buf[len], chain.dstport());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_RTP_static_chain(unsigned char *buf, const RTP__Static & chain)
{
int len = 0;
Log_function_name_on_enter();
len += Set_octetstring(&buf[len], chain.ssrc());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_RTP_dynamic_chain(unsigned char *buf, const RTP__Dynamic & chain)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("RTP version", chain.vfield(), 2);
buf[len] = (chain.vfield() << 6) & 0xC0;
buf[len] += ShiftUpBit(*chain.pbit(), 5);
buf[len] += ShiftUpBit(*chain.rxbit(), 4);
buf[len] += chain.ccfield() & 0x0F;
len += 1;
buf[len] = ShiftUpBit(*chain.mbit(), 7);
buf[len] += chain.ptfield() & 0x7F;
len += 1;
len += Set_LIN2_BO_LAST(&buf[len], chain.rtpseqnum());
len += Set_LIN4_BO_LAST(&buf[len], chain.rtpts());
len += Set_Encoding_Type_0(&buf[len], chain.gencsrclist());
Check_field_presence("RTP rx", *chain.rxbit() == 1,
chain.rx__field().ispresent());
if (chain.rx__field().ispresent())
{
Check_field_value("RX reserved", (int) *chain.rx__field()().reserved(), 0);
buf[len] = ((*chain.rx__field()().reserved()) << 5) & 0xE0;
buf[len] += ShiftUpBit(*chain.rx__field()().xbit(), 4);
buf[len] += (chain.rx__field()().mode() << 2) & 0x0C;
buf[len] += ShiftUpBit(*chain.rx__field()().tisbit(), 1);
buf[len] += ShiftUpBit(*chain.rx__field()().tssbit(), 0);
len += 1;
}
Check_field_presence("TS Stride",
chain.rx__field().ispresent() &&
(*chain.rx__field()().tssbit()) == 1,
chain.ts__stride().ispresent());
Check_field_presence("TIME Stride",
chain.rx__field().ispresent() &&
(*chain.rx__field()().tisbit()) == 1,
chain.time__stride().ispresent());
len += Set_SDVL_field_opt(&buf[len], chain.ts__stride(), 0);
len += Set_SDVL_field_opt(&buf[len], chain.time__stride(), 0);
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_RTP_flags_fields_opt(unsigned char *buf,
const OPTIONAL < RTP__flags__fields > &field)
{
int len = 0;
Log_function_name_on_enter();
if (!field.ispresent())
{
Log_function_name_on_leave();
return len;
}
buf[len] = (field().mode() << 6) & 0xC0;
buf[len] += ShiftUpBit(*field().r__pt(), 5);
buf[len] += ShiftUpBit(*field().m__bit(), 4);
buf[len] += ShiftUpBit(*field().r__x(), 3);
buf[len] += ShiftUpBit(*field().csrc(), 2);
buf[len] += ShiftUpBit(*field().tss(), 1);
buf[len] += ShiftUpBit(*field().tis(), 0);
len += 1;
Check_field_presence("RTP flags",
*field().r__pt() == 1, field().flags().ispresent());
if (field().flags().ispresent())
{
buf[len] = (((*field().flags()().r__p()) << 7) & 0x80) +
(field().flags()().rtp__pt() & 0x7F);
len += 1;
}
Check_field_presence("Compressed CSRC list",
*field().csrc() == 1, field().csrc__list().ispresent());
len += Set_Compr_head_list_opt(&buf[len], field().csrc__list());
Check_field_presence("TS_STRIDE",
*field().tss() == 1, field().ts__stride().ispresent());
len += Set_SDVL_field_opt(&buf[len], field().ts__stride(), 0);
Check_field_presence("TIME_STRIDE",
*field().tis() == 1,
field().time__stride().ispresent());
len += Set_SDVL_field_opt(&buf[len], field().time__stride(), 0);
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_IPv4_dynamic_chain(unsigned char *buf, const IPv4__Dynamic & chain)
{
int len = 0;
Log_function_name_on_enter();
len += Set_LIN1(&buf[len], chain.tos());
len += Set_LIN1(&buf[len], chain.ttl());
len += Set_LIN2_BO_LAST(&buf[len], chain.identification());
buf[len] = ShiftUpBit(*chain.df__bit(), 7);
buf[len] += ShiftUpBit(*chain.rnd__bit(), 6);
buf[len] += ShiftUpBit(*chain.nbo__bit(), 5);
Check_field_value("IPv4 reserved (dynamic chain)", *chain.reserved(), 0);
buf[len] += (*chain.reserved()) & 0x1F;
len += 1;
len += Set_Encoding_Type_0(&buf[len], chain.genextheadlist());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_IPv6_dynamic_chain(unsigned char *buf, const IPv6__Dynamic & chain)
{
int len = 0;
Log_function_name_on_enter();
len += Set_LIN1(&buf[len], chain.trafficclass());
len += Set_LIN1(&buf[len], chain.hoplimit());
len += Set_Encoding_Type_0(&buf[len], chain.genextheadlist());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
/* ============ Encoding functions for ROHC types ============ */
int
Set_feedback(unsigned char *buf, const Feedback__u & feedback,
BOOLEAN const &large_cid)
{
int len = 0, crcpos = 0, crcstart = 0;
Log_function_name_on_enter();
Check_field_value("feedback type", (int) *feedback.feedback__type(), 30);
Check_feedback_code__size(feedback.code(), feedback.size());
buf[len] = ((*feedback.feedback__type()) << 3) & 0xF8;
buf[len] += feedback.code() & 0x07;
len += 1;
len += Set_LIN1_opt(&buf[len], feedback.size());
crcstart = len;
len += Set_CID(&buf[len], feedback.feedback__data().cid(), large_cid);
switch (feedback.feedback__data().feedback__type().get_selection())
{
case Feedback__type::ALT_feedback1:
{
Feedback1 fback1 =
feedback.feedback__data().feedback__type().feedback1();
len += Set_octetstring(&buf[len], fback1);
break;
}
case Feedback__type::ALT_feedback2:
{
Feedback2 fback2 =
feedback.feedback__data().feedback__type().feedback2();
buf[len] = (fback2.acktype() << 6) & 0xC0;
buf[len] += (fback2.mode() << 4) & 0x30;
buf[len] += (fback2.sn() >> 8) & 0x0F;
len += 1;
buf[len] = fback2.sn() & 0xFF;
len += 1;
if (fback2.feedback__opts().ispresent())
{
Feedback__opts & fbopts = fback2.feedback__opts();
for (int num = 0; num < fbopts.size_of(); num++)
{
buf[len] = (fbopts[num].opt__type() << 4) & 0xF0;
Check_feedback_optlen__optsize(fbopts[num].opt__len(),
fbopts[num].opt__data());
buf[len] += fbopts[num].opt__len() & 0x0F;
len += 1;
len += Set_octetstring_opt(&buf[len], fbopts[num].opt__data());
if (fbopts[num].opt__data().ispresent())
{
if ((fbopts[num].opt__len() == 1)
&& (fbopts[num].opt__type() == 1) && (buf[len - 1] == 0))
crcpos = len - 1;
}
}
}
break;
}
default:
break;
}
if (feedback.size().ispresent() && feedback.size() == 0)
{
buf[1] = (len - 2) & 0xFF;
}
if ((!feedback.size().ispresent()) && feedback.code() == 0)
{
buf[0] = (buf[0] & 0xF8) + ((len - 1) & 0x07);
}
if ((crcpos > crcstart) && (buf[crcpos] == 0))
buf[crcpos] = ComputeCRC(&(buf[crcstart]), len - crcstart, 8);
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_ROHC_Feedback_opt(unsigned char *buf,
const OPTIONAL < Feedback > &feedback,
BOOLEAN const &large_cid)
{
int len = 0;
Log_function_name_on_enter();
if (!feedback.ispresent())
{
Log_function_name_on_leave();
return len;
}
for (int num = 0; num < feedback().size_of(); num++)
{
len += Set_feedback(&buf[len], feedback()[num], large_cid);
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
/* Inserts CID infomation into the buffer by moving memory areas */
int
Set_CID_for_packets(unsigned char *buf, ROHC__config const &config,
int cid, int buflen)
{
int len = 0;
Log_function_name_on_enter();
if (config.large__cid() == false)
{ /* Small CID: first octet is the CID */
if (cid > 0)
{
// Overlapping memory areas, use memmove
memmove(&(buf[1]), &(buf[0]), buflen);
buf[0] = 0xE0 + (cid & 0x0F);
len += 1;
}
}
else
{ /* Large CID: CID is placed after the first octet */
int cidlen = SDVL_encoded_CID_length(cid);
// Overlapping memory areas, use memmove
memmove(&(buf[1 + cidlen]), &(buf[1]), buflen - 1);
len += Set_SDVL_field(&(buf[1]), cid, 0);
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_ROHC_Header_Profile0(unsigned char *buf,
const Profile0__headers & hdr,
ROHC__config const &config)
{
int len = 0, crcpos = 0, cidlen, cid;
Log_function_name_on_enter();
switch (hdr.get_selection())
{
case Profile0__headers::ALT_ir:
{
cid = hdr.ir().cid();
Check_field_value("packet type", (int) *hdr.ir().type__ind(), 126);
buf[len] = ((*hdr.ir().type__ind()) << 1) & 0xFE;
buf[len] += (*hdr.ir().d()) & 0x01;
len += 1;
Check_field_value("profile", hdr.ir().profile(), 0);
len += Set_LIN1(&buf[len], hdr.ir().profile());
crcpos = len;
len += Set_LIN1(&buf[len], hdr.ir().crc());
len += Set_octetstring(&buf[len], hdr.ir().orig__packet());
break;
}
case Profile0__headers::ALT_normal:
{
cid = hdr.normal().cid();
len += Set_octetstring(&buf[len], hdr.normal().orig__packet());
break;
}
default:
Log_not_implemented_union_field("Profile0_headers", hdr.get_selection());
break;
}
cidlen = Set_CID_for_packets(buf, config, cid, len);
crcpos += cidlen;
len += cidlen;
if (hdr.get_selection() == Profile0__headers::ALT_ir && hdr.ir().crc() == 0)
{
buf[crcpos] = ComputeCRC(&(buf[0]), crcpos, 8);
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Static_Chain_Profile1(unsigned char *buf, const Static__Chain & chain)
{
int len = 0;
Log_function_name_on_enter();
for (int num = 0; num < chain.size_of(); num++)
{
switch (chain[num].get_selection())
{
case Static__Chain__u::ALT_ipv4__stat:
len += Set_IPv4_static_chain(&buf[len], chain[num].ipv4__stat());
break;
case Static__Chain__u::ALT_ipv6__stat:
len += Set_IPv6_static_chain(&buf[len], chain[num].ipv6__stat());
break;
case Static__Chain__u::ALT_udp__stat:
len += Set_UDP_static_chain(&buf[len], chain[num].udp__stat());
break;
case Static__Chain__u::ALT_rtp__stat:
len += Set_RTP_static_chain(&buf[len], chain[num].rtp__stat());
break;
default:
Log_not_implemented_union_field
("Static_Chain_u", chain[num].get_selection());
break;
}
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Dynamic_Chain_Profile1(unsigned char *buf, const Dynamic__Chain & dynch)
{
int len = 0;
Log_function_name_on_enter();
for (int num = 0; num < dynch.size_of(); num++)
{
switch (dynch[num].get_selection())
{
case Dynamic__Chain__u::ALT_ipv4__dyn:
len += Set_IPv4_dynamic_chain(&buf[len], dynch[num].ipv4__dyn());
break;
case Dynamic__Chain__u::ALT_ipv6__dyn:
len += Set_IPv6_dynamic_chain(&buf[len], dynch[num].ipv6__dyn());
break;
case Dynamic__Chain__u::ALT_udp__dyn:
len += Set_LIN2_BO_LAST(&buf[len], dynch[num].udp__dyn().cksum());
break;
case Dynamic__Chain__u::ALT_rtp__dyn:
len += Set_RTP_dynamic_chain(&buf[len], dynch[num].rtp__dyn());
break;
default:
Log_not_implemented_union_field
("Dynamic_Chain_u", dynch[num].get_selection());
break;
}
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_ir(unsigned char *buf,
const Profile1__IR__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 126);
buf[len] = ((*hdr.type__ind()) << 1) & 0xFE;
Check_field_presence("dynamic chain", *hdr.d() == 1,
hdr.dyn__chain().ispresent());
buf[len] += ShiftUpBit(*hdr.d(), 0);
len += 1;
Check_field_value("profile", hdr.profile(), 1);
len += Set_LIN1(&buf[len], hdr.profile());
len += Set_LIN1(&buf[len], hdr.crc());
len += Set_Static_Chain_Profile1(&buf[len], hdr.stat__chain());
if (hdr.dyn__chain().ispresent())
len += Set_Dynamic_Chain_Profile1(&buf[len], hdr.dyn__chain());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_irdyn(unsigned char *buf,
const Profile1__IR__DYN__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 248);
buf[len] = *hdr.type__ind();
len += 1;
Check_field_value("profile", hdr.profile(), 1);
len += Set_LIN1(&buf[len], hdr.profile());
len += Set_LIN1(&buf[len], hdr.crc());
len += Set_Dynamic_Chain_Profile1(&buf[len], hdr.dyn__chain());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_r0(unsigned char *buf,
const Profile1__R__0__header & hdr)
{
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 0);
buf[0] = ((*hdr.type__ind()) << 6) & 0xC0;
buf[0] += hdr.sn() & 0x3F;
Log_hexdump(buf, 1);
Log_function_name_on_leave();
return 1;
}
int
Set_Profile1_ROHC_Header_r0crc(unsigned char *buf,
const Profile1__R__0__CRC__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 1);
buf[len] = ((*hdr.type__ind()) << 6) & 0xC0;
buf[len] += (hdr.sn() >> 1) & 0x3F;
len += 1;
buf[len] = (hdr.sn() << 7) & 0x80;
buf[len] += hdr.crc() & 0x7F;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_uo0(unsigned char *buf,
const Profile1__UO__0__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 0);
buf[len] = ((*hdr.type__ind()) << 7) & 0x80;
buf[len] += (hdr.sn() << 3) & 0x78;
buf[len] += hdr.crc() & 0x07;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_r1(unsigned char *buf,
const Profile1__R__1__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 2);
buf[len] = ((*hdr.type__ind()) << 6) & 0xC0;
buf[len] += hdr.sn() & 0x3F;
len += 1;
buf[len] = ShiftUpBit(*hdr.m__bit(), 7);
buf[len] += ShiftUpBit(*hdr.x__bit(), 6);
buf[len] += hdr.ts() & 0x3F;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_r1id(unsigned char *buf,
const Profile1__R__1__ID__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 2);
buf[len] = ((*hdr.type__ind()) << 6) & 0xC0;
buf[len] += hdr.sn() & 0x3F;
len += 1;
buf[len] = ShiftUpBit(*hdr.m__bit(), 7);
buf[len] += ShiftUpBit(*hdr.x__bit(), 6);
Check_field_value("T-bit", (int) *hdr.t__bit(), 0);
buf[len] += ShiftUpBit(*hdr.t__bit(), 5);
buf[len] += hdr.ip__id() & 0x1F;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_r1ts(unsigned char *buf,
const Profile1__R__1__TS__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 2);
buf[len] = ((*hdr.type__ind()) << 6) & 0xC0;
buf[len] += hdr.sn() & 0x3F;
len += 1;
buf[len] = ShiftUpBit(*hdr.m__bit(), 7);
buf[len] += ShiftUpBit(*hdr.x__bit(), 6);
Check_field_value("T-bit", (int) *hdr.t__bit(), 1);
buf[len] += ShiftUpBit(*hdr.t__bit(), 5);
buf[len] += hdr.ts() & 0x1F;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_uo1(unsigned char *buf,
const Profile1__UO__1__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 2);
buf[len] = ((*hdr.type__ind()) << 6) & 0xC0;
buf[len] += hdr.ts() & 0x3F;
len += 1;
buf[len] = ShiftUpBit(*hdr.m__bit(), 7);
buf[len] += (hdr.sn() << 3) & 0x78;
buf[len] += hdr.crc() & 0x07;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_uo1id(unsigned char *buf,
const Profile1__UO__1__ID__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 2);
buf[len] = ((*hdr.type__ind()) << 6) & 0xC0;
Check_field_value("T-bit", (int) *hdr.t__bit(), 0);
buf[len] += ShiftUpBit(*hdr.t__bit(), 5);
buf[len] += hdr.ip__id() & 0x1F;
len += 1;
buf[len] = ShiftUpBit(*hdr.x__bit(), 7);
buf[len] += (hdr.sn() << 3) & 0x78;
buf[len] += hdr.crc() & 0x07;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_uo1ts(unsigned char *buf,
const Profile1__UO__1__TS__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 2);
buf[len] = ((*hdr.type__ind()) << 6) & 0xC0;
Check_field_value("T-bit", (int) *hdr.t__bit(), 1);
buf[len] += ShiftUpBit(*hdr.t__bit(), 5);
buf[len] += hdr.ts() & 0x1F;
len += 1;
buf[len] = ShiftUpBit(*hdr.m__bit(), 7);
buf[len] += (hdr.sn() << 3) & 0x78;
buf[len] += hdr.crc() & 0x07;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_uor2(unsigned char *buf,
const Profile1__UOR__2__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 6);
buf[len] = ((*hdr.type__ind()) << 5) & 0xE0;
buf[len] += (hdr.ts() >> 1) & 0x1F;
len += 1;
buf[len] = (hdr.ts() << 7) & 0x80;
buf[len] += ShiftUpBit(*hdr.m__bit(), 6);
buf[len] += hdr.sn() & 0x3F;
len += 1;
buf[len] = ShiftUpBit(*hdr.x__bit(), 7);
buf[len] += hdr.crc() & 0x7F;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_uor2id(unsigned char *buf,
const Profile1__UOR__2__ID__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 6);
buf[len] = ((*hdr.type__ind()) << 5) & 0xE0;
buf[len] += hdr.ip__id() & 0x1F;
len += 1;
Check_field_value("T-bit", (int) *hdr.t__bit(), 0);
buf[len] = ShiftUpBit(*hdr.t__bit(), 7);
buf[len] += ShiftUpBit(*hdr.m__bit(), 6);
buf[len] += hdr.sn() & 0x3F;
len += 1;
buf[len] = ShiftUpBit(*hdr.x__bit(), 7);
buf[len] += hdr.crc() & 0x7F;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_uor2ts(unsigned char *buf,
const Profile1__UOR__2__TS__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 6);
Log_hexdump(buf, len);
buf[len] = ((*hdr.type__ind()) << 5) & 0xE0;
buf[len] += hdr.ts() & 0x1F;
len += 1;
Check_field_value("T-bit", (int) *hdr.t__bit(), 1);
buf[len] = ShiftUpBit(*hdr.t__bit(), 7);
buf[len] += ShiftUpBit(*hdr.m__bit(), 6);
buf[len] += hdr.sn() & 0x3F;
len += 1;
buf[len] = ShiftUpBit(*hdr.x__bit(), 7);
buf[len] += hdr.crc() & 0x7F;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_Inner_IP_flags_opt(unsigned char *buf,
const OPTIONAL < Inner__IP__flags > &field)
{
int len = 0;
Log_function_name_on_enter();
if (!field.ispresent())
{
Log_function_name_on_leave();
return len;
}
buf[len] = ShiftUpBit(*field().tos(), 7);
buf[len] += ShiftUpBit(*field().ttl(), 6);
buf[len] += ShiftUpBit(*field().df(), 5);
buf[len] += ShiftUpBit(*field().pr(), 4);
buf[len] += ShiftUpBit(*field().ipx(), 3);
buf[len] += ShiftUpBit(*field().nbo(), 2);
buf[len] += ShiftUpBit(*field().rnd__bit(), 1);
buf[len] += ShiftUpBit(*field().ip2__bit(), 0);
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_Outer_IP_flags_opt(unsigned char *buf,
const OPTIONAL < Outer__IP__flags > &field)
{
int len = 0;
Log_function_name_on_enter();
if (!field.ispresent())
{
Log_function_name_on_leave();
return len;
}
buf[len] = ShiftUpBit(*field().tos2(), 7);
buf[len] += ShiftUpBit(*field().ttl2(), 6);
buf[len] += ShiftUpBit(*field().df2(), 5);
buf[len] += ShiftUpBit(*field().pr2(), 4);
buf[len] += ShiftUpBit(*field().ipx2(), 3);
buf[len] += ShiftUpBit(*field().nbo2(), 2);
buf[len] += ShiftUpBit(*field().rnd2(), 1);
buf[len] += ShiftUpBit(*field().i2__bit(), 0);
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ipx_headers_opt(unsigned char *buf,
const OPTIONAL < IP__Ext__heads > &field)
{
int len = 0;
Log_function_name_on_enter();
if (!field.ispresent())
{
Log_function_name_on_leave();
return len;
}
buf[len] = ShiftUpBit(*field().cl(), 7);
buf[len] += ShiftUpBit(*field().aseq(), 6);
buf[len] += ShiftUpBit(*field().eseq(), 5);
buf[len] += ShiftUpBit(*field().gseq(), 4);
buf[len] += (*field().res()) & 0x0F;
len += 1;
Check_field_presence("AH SN", *field().aseq() == 1,
field().ah__seq().ispresent());
Check_field_presence("ESP SN", *field().eseq() == 1,
field().esp__seq().ispresent());
Check_field_presence("GRE SN", *field().gseq() == 1,
field().gre__seq().ispresent());
Check_field_presence("Compressed header list", *field().cl() == 1,
field().compr__head__list().ispresent());
len += Set_AEGSeqnum_opt(&buf[len], field().ah__seq());
len += Set_AEGSeqnum_opt(&buf[len], field().esp__seq());
len += Set_AEGSeqnum_opt(&buf[len], field().gre__seq());
len += Set_Compr_head_list_opt(&buf[len], field().compr__head__list());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_Inner_IP_fields_opt(unsigned char *buf,
const OPTIONAL < Inner__IP__flags > &flags,
const OPTIONAL < Inner__IP__fields > &field)
{
int len = 0;
Log_function_name_on_enter();
if (!field.ispresent())
{
Log_function_name_on_leave();
return len;
}
Check_field_presence("TOS (inner IP)",
flags.ispresent() && (*flags().tos() == 1),
field().tos().ispresent());
len += Set_LIN1_opt(&buf[len], field().tos());
Check_field_presence("TTL (inner IP)",
flags.ispresent() && (*flags().ttl() == 1),
field().ttl().ispresent());
len += Set_LIN1_opt(&buf[len], field().ttl());
Check_field_presence("PROTO (inner IP)",
flags.ispresent() && (*flags().pr() == 1),
field().proto().ispresent());
len += Set_LIN1_opt(&buf[len], field().proto());
Check_field_presence("IP extension headers (inner IP)",
flags.ispresent() && (*flags().ipx() == 1),
field().ext__heads().ispresent());
len += Set_Profile1_ipx_headers_opt(&buf[len], field().ext__heads());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_Outer_IP_fields_opt(unsigned char *buf,
const OPTIONAL < Outer__IP__flags > &flags,
const OPTIONAL < Outer__IP__fields > &field)
{
int len = 0;
Log_function_name_on_enter();
if (!field.ispresent())
{
Log_function_name_on_leave();
return len;
}
Check_field_presence("TOS (outer IP)",
flags.ispresent() && (*flags().tos2() == 1),
field().tos().ispresent());
len += Set_LIN1_opt(&buf[len], field().tos());
Check_field_presence("TTL (outer IP)",
flags.ispresent() && (*flags().ttl2() == 1),
field().ttl().ispresent());
len += Set_LIN1_opt(&buf[len], field().ttl());
Check_field_presence("PROTO (outer IP)",
flags.ispresent() && (*flags().pr2() == 1),
field().proto().ispresent());
len += Set_LIN1_opt(&buf[len], field().proto());
Check_field_presence("IP extension headers (outer IP)",
flags.ispresent() && (*flags().ipx2() == 1),
field().ext__heads().ispresent());
len += Set_Profile1_ipx_headers_opt(&buf[len], field().ext__heads());
Check_field_presence("IP-ID (outer IP)",
flags.ispresent() && (*flags().i2__bit() == 1),
field().ip__id().ispresent());
len += Set_LIN2_BO_LAST_opt(&buf[len], field().ip__id());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_Extension0(unsigned char *buf, const Extension0 & ext)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("extension type", (int) *ext.ext__type(), 0);
buf[len] = ((*ext.ext__type()) << 6) & 0xC0;
buf[len] += (ext.sn() << 3) & 0x38;
buf[len] += ext.plust() & 0x07;
len += 1;
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_Extension1(unsigned char *buf, const Extension1 & ext)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("extension type", (int) *ext.ext__type(), 1);
buf[len] = ((*ext.ext__type()) << 6) & 0xC0;
buf[len] += (ext.sn() << 3) & 0x38;
buf[len] += ext.plust() & 0x07;
len += 1;
len += Set_LIN1(&buf[len], ext.minust());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_Extension2(unsigned char *buf, const Extension2 & ext)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("extension type", (int) *ext.ext__type(), 2);
buf[len] = ((*ext.ext__type()) << 6) & 0xC0;
buf[len] += (ext.sn() << 3) & 0x38;
buf[len] += (ext.plust() >> 8) & 0x07;
len += 1;
buf[len] = ext.plust() & 0xFF;
len += 1;
len += Set_LIN1(&buf[len], ext.minust());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_Extension3(unsigned char *buf, const Extension3 & ext)
{
int len = 0;
int ts_length = 0;
Log_function_name_on_enter();
Check_field_value("extension type", (int) *ext.ext__type(), 3);
buf[len] = ((*ext.ext__type()) << 6) & 0xC0;
buf[len] += ShiftUpBit(*ext.s__bit(), 5);
buf[len] += ShiftUpBit(*ext.r__ts__bit(), 4);
buf[len] += ShiftUpBit(*ext.tsc__bit(), 3);
buf[len] += ShiftUpBit(*ext.i__bit(), 2);
buf[len] += ShiftUpBit(*ext.ip__bit(), 1);
buf[len] += ShiftUpBit(*ext.rtp__bit(), 0);
len += 1;
Check_field_presence("Inner IP flags",
*ext.ip__bit() == 1,
ext.inner__ip__flags().ispresent());
len += Set_Profile1_Inner_IP_flags_opt(&buf[len], ext.inner__ip__flags());
Check_field_presence("Outer IP flags",
ext.inner__ip__flags().ispresent() &&
(*ext.inner__ip__flags()().ip2__bit() == 1),
ext.outer__ip__flags().ispresent());
len += Set_Profile1_Outer_IP_flags_opt(&buf[len], ext.outer__ip__flags());
Check_field_presence("SN", *ext.s__bit() == 1, ext.sn().ispresent());
len += Set_LIN1_opt(&buf[len], ext.sn());
Check_field_presence("RTP TS", *ext.r__ts__bit() == 1, ext.ts().ispresent());
if (ext.ts__length().ispresent()) ts_length = ext.ts__length()();
len += Set_SDVL_field_opt(&buf[len], ext.ts(), ts_length);
Check_field_presence("Inner IP fields",
*ext.ip__bit() == 1, ext.inner__ip__hdr().ispresent());
len += Set_Profile1_Inner_IP_fields_opt(&buf[len], ext.inner__ip__flags(),
ext.inner__ip__hdr());
Check_field_presence("Inner IP-ID",
*ext.i__bit() == 1, ext.ip__id().ispresent());
len += Set_LIN2_BO_LAST_opt(&buf[len], ext.ip__id());
Check_field_presence("Outer IP fields",
ext.inner__ip__flags().ispresent() &&
(*ext.inner__ip__flags()().ip2__bit() == 1),
ext.outer__ip__hdr().ispresent());
len += Set_Profile1_Outer_IP_fields_opt(&buf[len], ext.outer__ip__flags(),
ext.outer__ip__hdr());
Check_field_presence("RTP flags and fields",
*ext.rtp__bit() == 1, ext.rtp__fl__fi().ispresent());
len += Set_RTP_flags_fields_opt(&buf[len], ext.rtp__fl__fi());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_Extension_opt(unsigned char *buf,
const OPTIONAL < Profile1__Extension >
&ext)
{
int len = 0;
Log_function_name_on_enter();
if (ext.ispresent())
{
if (ext().get_selection() == Profile1__Extension::ALT_ext0)
{
len += Set_Profile1_ROHC_Header_Extension0(&buf[len], ext().ext0());
}
else if (ext().get_selection() == Profile1__Extension::ALT_ext1)
{
len += Set_Profile1_ROHC_Header_Extension1(&buf[len], ext().ext1());
}
else if (ext().get_selection() == Profile1__Extension::ALT_ext2)
{
len += Set_Profile1_ROHC_Header_Extension2(&buf[len], ext().ext2());
}
else if (ext().get_selection() == Profile1__Extension::ALT_ext3)
{
len += Set_Profile1_ROHC_Header_Extension3(&buf[len], ext().ext3());
}
else
{
Log_not_implemented_union_field("Profile1_Extension",
ext().get_selection());
}
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header_ipid_ah_gre(unsigned char *buf,
const Profile1__headers & hdr)
{
int len = 0;
Log_function_name_on_enter();
len += Set_LIN2_BO_LAST_opt(&buf[len], hdr.ip__id__outer());
len += Set_octetstring_opt(&buf[len], hdr.ah__outer());
len += Set_LIN2_BO_LAST_opt(&buf[len], hdr.gre__cksum1());
len += Set_LIN2_BO_LAST_opt(&buf[len], hdr.ip__id__inner());
len += Set_octetstring_opt(&buf[len], hdr.ah__inner());
len += Set_LIN2_BO_LAST_opt(&buf[len], hdr.gre__cksum2());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile1_ROHC_Header(unsigned char *buf,
const Profile1__headers & hdr,
ROHC__config const &config)
{
int len = 0, crcpos = 0, cidlen = 0, cid;
Log_function_name_on_enter();
switch (hdr.base__header().get_selection())
{
case Profile1__base__header::ALT_ir:
cid = hdr.base__header().ir().cid();
crcpos = len + 2;
len += Set_Profile1_ROHC_Header_ir(&buf[len], hdr.base__header().ir());
break;
case Profile1__base__header::ALT_ir__dyn:
cid = hdr.base__header().ir__dyn().cid();
crcpos = len + 2;
len += Set_Profile1_ROHC_Header_irdyn(&buf[len],
hdr.base__header().ir__dyn());
break;
case Profile1__base__header::ALT_r__0:
cid = hdr.base__header().r__0().cid();
len += Set_Profile1_ROHC_Header_r0(&buf[len], hdr.base__header().r__0());
break;
case Profile1__base__header::ALT_r__0__crc:
cid = hdr.base__header().r__0__crc().cid();
len += Set_Profile1_ROHC_Header_r0crc(&buf[len],
hdr.base__header().r__0__crc());
break;
case Profile1__base__header::ALT_uo__0:
cid = hdr.base__header().uo__0().cid();
len += Set_Profile1_ROHC_Header_uo0(&buf[len], hdr.base__header().uo__0());
break;
case Profile1__base__header::ALT_r__1:
cid = hdr.base__header().r__1().cid();
len += Set_Profile1_ROHC_Header_r1(&buf[len], hdr.base__header().r__1());
break;
case Profile1__base__header::ALT_r__1__id:
cid = hdr.base__header().r__1__id().cid();
len +=
Set_Profile1_ROHC_Header_r1id(&buf[len], hdr.base__header().r__1__id());
break;
case Profile1__base__header::ALT_r__1__ts:
cid = hdr.base__header().r__1__ts().cid();
len +=
Set_Profile1_ROHC_Header_r1ts(&buf[len], hdr.base__header().r__1__ts());
break;
case Profile1__base__header::ALT_uo__1:
cid = hdr.base__header().uo__1().cid();
len += Set_Profile1_ROHC_Header_uo1(&buf[len], hdr.base__header().uo__1());
break;
case Profile1__base__header::ALT_uo__1__id:
cid = hdr.base__header().uo__1__id().cid();
len +=
Set_Profile1_ROHC_Header_uo1id(&buf[len],
hdr.base__header().uo__1__id());
break;
case Profile1__base__header::ALT_uo__1__ts:
cid = hdr.base__header().uo__1__ts().cid();
len +=
Set_Profile1_ROHC_Header_uo1ts(&buf[len],
hdr.base__header().uo__1__ts());
break;
case Profile1__base__header::ALT_uor__2:
cid = hdr.base__header().uor__2().cid();
len +=
Set_Profile1_ROHC_Header_uor2(&buf[len], hdr.base__header().uor__2());
break;
case Profile1__base__header::ALT_uor__2__id:
cid = hdr.base__header().uor__2__id().cid();
len +=
Set_Profile1_ROHC_Header_uor2id(&buf[len],
hdr.base__header().uor__2__id());
break;
case Profile1__base__header::ALT_uor__2__ts:
cid = hdr.base__header().uor__2__ts().cid();
len +=
Set_Profile1_ROHC_Header_uor2ts(&buf[len],
hdr.base__header().uor__2__ts());
break;
default:
Log_not_implemented_union_field
("Profile1_base_header", hdr.base__header().get_selection());
break;
}
len += Set_Profile1_ROHC_Header_Extension_opt(&buf[len], hdr.ext());
len += Set_Profile1_ROHC_Header_ipid_ah_gre(&buf[len], hdr);
len += Set_LIN2_BO_LAST_opt(&buf[len], hdr.udp__cksum());
cidlen = Set_CID_for_packets(buf, config, cid, len);
crcpos += cidlen;
len += cidlen;
if (hdr.base__header().get_selection() == Profile1__base__header::ALT_ir
&& hdr.base__header().ir().crc() == 0)
buf[crcpos] = ComputeCRC(&(buf[0]), len, 8);
else if (hdr.base__header().get_selection() ==
Profile1__base__header::ALT_ir__dyn
&& hdr.base__header().ir__dyn().crc() == 0)
buf[crcpos] = ComputeCRC(&(buf[0]), len, 8);
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile2_Static_Chain(unsigned char
*buf, const Profile2__Static__Chain & chain)
{
int len = 0;
Log_function_name_on_enter();
for (int num = 0; num < chain.size_of(); num++)
{
switch (chain[num].get_selection())
{
case Static__Chain__u::ALT_ipv4__stat:
len += Set_IPv4_static_chain(&buf[len], chain[num].ipv4__stat());
break;
case Static__Chain__u::ALT_ipv6__stat:
len += Set_IPv6_static_chain(&buf[len], chain[num].ipv6__stat());
break;
case Static__Chain__u::ALT_udp__stat:
len += Set_UDP_static_chain(&buf[len], chain[num].udp__stat());
break;
default:
Log_not_implemented_union_field
("Profile2_Static_Chain", chain[num].get_selection());
break;
}
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile2_Dynamic_Chain(unsigned char
*buf, const Profile2__Dynamic__Chain & dynch)
{
int len = 0;
Log_function_name_on_enter();
for (int num = 0; num < dynch.size_of(); num++)
{
switch (dynch[num].get_selection())
{
case Profile2__Dynamic__Chain__u::ALT_ipv4__dyn:
len += Set_IPv4_dynamic_chain(&buf[len], dynch[num].ipv4__dyn());
break;
case Profile2__Dynamic__Chain__u::ALT_ipv6__dyn:
len += Set_IPv6_dynamic_chain(&buf[len], dynch[num].ipv6__dyn());
break;
case Profile2__Dynamic__Chain__u::ALT_udp__dyn:
len += Set_LIN2_BO_LAST(&buf[len], dynch[num].udp__dyn().cksum());
len += Set_LIN2_BO_LAST(&buf[len], dynch[num].udp__dyn().udp__sn());
break;
default:
Log_not_implemented_union_field
("Profile2_Dynamic_Chain", dynch[num].get_selection());
break;
}
}
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile2_ROHC_Header_ir(unsigned char
*buf, const Profile2__IR__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 126);
buf[len] = ((*hdr.type__ind()) << 1) & 0xFE;
Check_field_presence("dynamic chain", *hdr.d() == 1,
hdr.dyn__chain().ispresent());
buf[len] += ShiftUpBit(*hdr.d(), 0);
len += 1;
Check_field_value("profile", hdr.profile(), 2);
len += Set_LIN1(&buf[len], hdr.profile());
len += Set_LIN1(&buf[len], hdr.crc());
len += Set_Profile2_Static_Chain(&buf[len], hdr.stat__chain());
if (hdr.dyn__chain().ispresent())
len += Set_Profile2_Dynamic_Chain(&buf[len], hdr.dyn__chain());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile2_ROHC_Header_irdyn(unsigned
char *buf,
const Profile2__IR__DYN__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 248);
buf[len] = *hdr.type__ind();
len += 1;
Check_field_value("profile", hdr.profile(), 2);
len += Set_LIN1(&buf[len], hdr.profile());
len += Set_LIN1(&buf[len], hdr.crc());
len += Set_Profile2_Dynamic_Chain(&buf[len], hdr.dyn__chain());
Log_hexdump(buf, len);
Log_function_name_on_leave();
return len;
}
int
Set_Profile2_ROHC_Header_r1(unsigned char
*buf, const Profile2__R__1__header & hdr)
{
int len = 0;
Log_function_name_on_enter();
Check_field_value("packet type", (int) *hdr.type__ind(), 2);
buf[len] = ((*hdr.type__ind()) << 6) & 0xC0;
buf[len] += hdr.sn() & 0x3F;
len += 1;
buf[len] = ShiftUpBit(*hdr.x__bit(), 7);
buf[len] += hdr.ip__id() & 0x7F;
len += 1;