epan: centralize SDNV processing along other similar varint types
This avoids having general-purpose decoding happening in non-DLL-exported functions defined in a dissector for #18478, and removes unused functions and avoids duplicate decoding. This also removes unnecessary early exit conditions for #18145. Unit test cases for varint decoding are added to verify this.
This commit is contained in:
parent
d2e5bd80cb
commit
5bb756e203
|
@ -56,8 +56,16 @@ static int dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_
|
|||
extern void
|
||||
dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
|
||||
|
||||
|
||||
static int evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount);
|
||||
|
||||
/// Return an error_info index if not valid
|
||||
static int evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **error);
|
||||
|
||||
static int add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_sdnv_time);
|
||||
|
||||
static gint64
|
||||
evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount);
|
||||
|
||||
static int proto_bundle = -1;
|
||||
static dissector_handle_t bundle_handle = NULL;
|
||||
|
@ -1834,48 +1842,24 @@ display_extension_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int
|
|||
}
|
||||
|
||||
/*3rd arg is number of bytes in field (returned)*/
|
||||
int
|
||||
static int
|
||||
evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount)
|
||||
{
|
||||
int value = 0;
|
||||
guint8 curbyte;
|
||||
guint64 value = 0;
|
||||
*bytecount = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &value, ENC_VARINT_SDNV);
|
||||
|
||||
*bytecount = 0;
|
||||
|
||||
if (!tvb_bytes_exist(tvb, offset, 1)) {
|
||||
if (*bytecount == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get 1st byte and continue to get them while high-order bit is 1
|
||||
*/
|
||||
|
||||
while ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK) {
|
||||
if (*bytecount >= (int) sizeof(int)) {
|
||||
*bytecount = 0;
|
||||
return -1;
|
||||
}
|
||||
value = value << 7;
|
||||
value |= (curbyte & SDNV_MASK);
|
||||
++offset;
|
||||
++*bytecount;
|
||||
|
||||
if (!tvb_bytes_exist(tvb, offset, 1)) {
|
||||
return -1;
|
||||
}
|
||||
if (value > G_MAXINT) {
|
||||
ws_warning("evaluate_sdnv decoded a value too large to fit in an int, truncating");
|
||||
return G_MAXINT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add in the byte whose high-order bit is 0 (last one)
|
||||
*/
|
||||
|
||||
value = value << 7;
|
||||
value |= (curbyte & SDNV_MASK);
|
||||
++*bytecount;
|
||||
return value;
|
||||
return (int)value;
|
||||
}
|
||||
|
||||
int evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **error) {
|
||||
static int
|
||||
evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **error) {
|
||||
int value = evaluate_sdnv(tvb, offset, bytecount);
|
||||
*error = (value < 0) ? &ei_bundle_sdnv_length : NULL;
|
||||
return value;
|
||||
|
@ -1883,199 +1867,18 @@ int evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **e
|
|||
|
||||
/* Special Function to evaluate 64 bit SDNVs */
|
||||
/*3rd arg is number of bytes in field (returned)*/
|
||||
gint64
|
||||
static gint64
|
||||
evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount)
|
||||
{
|
||||
gint64 value = 0;
|
||||
guint8 curbyte;
|
||||
guint64 val = 0;
|
||||
*bytecount = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &val, ENC_VARINT_SDNV);
|
||||
|
||||
*bytecount = 0;
|
||||
|
||||
if (!tvb_bytes_exist(tvb, offset, 1)) {
|
||||
if (*bytecount == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get 1st byte and continue to get them while high-order bit is 1
|
||||
*/
|
||||
|
||||
while ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK) {
|
||||
if (*bytecount >= (int) sizeof(gint64)) {
|
||||
*bytecount = 0;
|
||||
return -1;
|
||||
}
|
||||
value = value << 7;
|
||||
value |= (curbyte & SDNV_MASK);
|
||||
++offset;
|
||||
++*bytecount;
|
||||
|
||||
if (!tvb_bytes_exist(tvb, offset, 1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add in the byte whose high-order bit is 0 (last one)
|
||||
*/
|
||||
|
||||
value = value << 7;
|
||||
value |= (curbyte & SDNV_MASK);
|
||||
++*bytecount;
|
||||
return value;
|
||||
return val & G_MAXINT64;
|
||||
}
|
||||
|
||||
/* Special Function to evaluate 32 bit unsigned SDNVs with error indication
|
||||
* bytecount returns the number bytes consumed
|
||||
* value returns the actual value
|
||||
*
|
||||
* result is TRUE (1) on success else FALSE (0)
|
||||
*/
|
||||
int
|
||||
evaluate_sdnv32(tvbuff_t *tvb, int offset, int *bytecount, guint32 *value)
|
||||
{
|
||||
int result;
|
||||
int num_bits_in_value;
|
||||
guint8 curbyte;
|
||||
guint8 high_bit;
|
||||
|
||||
*value = 0;
|
||||
*bytecount = 0;
|
||||
|
||||
result = FALSE;
|
||||
num_bits_in_value = 0;
|
||||
|
||||
if (tvb_bytes_exist(tvb, offset, 1)) {
|
||||
/*
|
||||
* Get 1st byte and continue to get them while high-order bit is 1
|
||||
*/
|
||||
result = TRUE;
|
||||
|
||||
/* Determine number of non-zero bits in first SDNV byte */
|
||||
/* technically 0x80 0x80 ... 0x81 is a valid inefficient representation of "1" */
|
||||
while ((0 == num_bits_in_value) && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) {
|
||||
if (!tvb_bytes_exist(tvb, offset, 1)) {
|
||||
result = FALSE;
|
||||
break;
|
||||
} else {
|
||||
num_bits_in_value = 7;
|
||||
high_bit = 0x40;
|
||||
while ((num_bits_in_value > 0) && (!(curbyte & high_bit))) {
|
||||
--num_bits_in_value;
|
||||
high_bit = high_bit >> 1;
|
||||
}
|
||||
|
||||
*value |= (curbyte & SDNV_MASK);
|
||||
++offset;
|
||||
++*bytecount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Process additional bytes that have the high order bit set */
|
||||
while (result && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) {
|
||||
/* Since the high order bit is set there must be 7 low order bits after this byte */
|
||||
if (!tvb_bytes_exist(tvb, offset, 1) || ((num_bits_in_value + 7) > (32 - 7))) {
|
||||
result = FALSE;
|
||||
} else {
|
||||
*value = *value << 7;
|
||||
*value |= (curbyte & SDNV_MASK);
|
||||
++offset;
|
||||
++*bytecount;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
/*
|
||||
* Add in the byte whose high-order bit is 0 (last one)
|
||||
*/
|
||||
*value = *value << 7;
|
||||
*value |= (curbyte & SDNV_MASK);
|
||||
++*bytecount;
|
||||
} else {
|
||||
*bytecount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Special Function to evaluate 64 bit unsigned SDNVs with error indication
|
||||
* bytecount returns the number bytes consumed or zero on error
|
||||
* value returns the actual value
|
||||
*
|
||||
* result is TRUE (1) on success else FALSE (0)
|
||||
*/
|
||||
int
|
||||
evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value)
|
||||
{
|
||||
int result;
|
||||
int num_bits_in_value;
|
||||
guint8 curbyte;
|
||||
guint8 high_bit;
|
||||
|
||||
*value = 0;
|
||||
*bytecount = 0;
|
||||
|
||||
result = FALSE;
|
||||
num_bits_in_value = 0;
|
||||
|
||||
if (tvb_bytes_exist(tvb, offset, 1)) {
|
||||
/*
|
||||
* Get 1st byte and continue to get them while high-order bit is 1
|
||||
*/
|
||||
result = TRUE;
|
||||
|
||||
/* Determine number of non-zero bits in first SDNV byte */
|
||||
/* technically 0x80 0x80 ... 0x81 is a valid inefficient representation of "1" */
|
||||
while ((0 == num_bits_in_value) && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) {
|
||||
if (!tvb_bytes_exist(tvb, offset, 1)) {
|
||||
result = FALSE;
|
||||
break;
|
||||
} else {
|
||||
num_bits_in_value = 7;
|
||||
high_bit = 0x40;
|
||||
while ((num_bits_in_value > 0) && (!(curbyte & high_bit))) {
|
||||
--num_bits_in_value;
|
||||
high_bit = high_bit >> 1;
|
||||
}
|
||||
|
||||
*value |= (curbyte & SDNV_MASK);
|
||||
++offset;
|
||||
++*bytecount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Process additional bytes that have the high order bit set */
|
||||
while (result && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) {
|
||||
/* Since the high order bit is set there must be 7 low order bits after this byte */
|
||||
if (!tvb_bytes_exist(tvb, offset, 1) || ((num_bits_in_value + 7) > (64 - 7))) {
|
||||
result = FALSE;
|
||||
} else {
|
||||
*value = *value << 7;
|
||||
*value |= (curbyte & SDNV_MASK);
|
||||
++offset;
|
||||
++*bytecount;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
/*
|
||||
* Add in the byte whose high-order bit is 0 (last one)
|
||||
*/
|
||||
*value = *value << 7;
|
||||
*value |= (curbyte & SDNV_MASK);
|
||||
++*bytecount;
|
||||
} else {
|
||||
*bytecount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dissect_bpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||
{
|
||||
|
|
|
@ -112,33 +112,6 @@ extern "C" {
|
|||
#define DTN_SCHEME_STR "dtn"
|
||||
#define IPN_SCHEME_STR "ipn"
|
||||
|
||||
/*
|
||||
* SDNV has a zero in high-order bit position of last byte. The high-order
|
||||
* bit of all preceding bytes is set to one. This returns the numeric value
|
||||
* in an integer and sets the value of the second argument to the number of
|
||||
* bytes used to code the SDNV. A -1 is returned if the evaluation fails
|
||||
* (value exceeds maximum for signed integer). 0 is an acceptable value.
|
||||
*/
|
||||
#define SDNV_MASK 0x7f
|
||||
|
||||
int evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount);
|
||||
|
||||
/// Return an error_info index if not valid
|
||||
int evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **error);
|
||||
|
||||
gint64 evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount);
|
||||
|
||||
|
||||
/* Special Functions to evaluate unsigned SDNVs with error indication
|
||||
* bytecount returns the number bytes consumed
|
||||
* value returns the actual value
|
||||
*
|
||||
* result is TRUE (1) on success else FALSE (0)
|
||||
*/
|
||||
int evaluate_sdnv32(tvbuff_t *tvb, int offset, int *bytecount, guint32 *value);
|
||||
|
||||
int evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -44,14 +44,10 @@
|
|||
#include <wsutil/wmem/wmem_map.h>
|
||||
#include <wsutil/wmem/wmem_interval_tree.h>
|
||||
|
||||
#include "packet-bpv6.h"
|
||||
|
||||
void proto_register_ltp(void);
|
||||
void proto_reg_handoff_ltp(void);
|
||||
|
||||
#define LTP_MIN_DATA_BUFFER 5
|
||||
#define LTP_MAX_HDR_EXTN 16
|
||||
#define LTP_MAX_TRL_EXTN 16
|
||||
|
||||
/// Unique session identifier
|
||||
typedef struct {
|
||||
|
@ -333,7 +329,6 @@ static int hf_ltp_fragment_count = -1;
|
|||
static int hf_ltp_reassembled_in = -1;
|
||||
static int hf_ltp_reassembled_length = -1;
|
||||
|
||||
static expert_field ei_ltp_neg_reception_claim_count = EI_INIT;
|
||||
static expert_field ei_ltp_mal_reception_claim = EI_INIT;
|
||||
static expert_field ei_ltp_sdnv_length = EI_INIT;
|
||||
static expert_field ei_ltp_sno_larger_than_ccsds = EI_INIT;
|
||||
|
@ -445,24 +440,16 @@ static const fragment_items ltp_frag_items = {
|
|||
"LTP fragments"
|
||||
};
|
||||
|
||||
static int
|
||||
add_sdnv64_to_tree(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, int offset, int hf_sdnv, guint64 *value, proto_item** item_ret)
|
||||
static proto_item *
|
||||
add_sdnv64_to_tree(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, int offset, int hf_sdnv, guint64 *retval, gint *lenretval)
|
||||
{
|
||||
int sdnv_status;
|
||||
int sdnv_length;
|
||||
guint64 sdnv_value;
|
||||
proto_item* ti;
|
||||
proto_item *ti;
|
||||
ti = proto_tree_add_item_ret_varint(tree, hf_sdnv, tvb, offset, -1, ENC_VARINT_SDNV, retval, lenretval);
|
||||
|
||||
sdnv_status = evaluate_sdnv64(tvb, offset, &sdnv_length, &sdnv_value);
|
||||
ti = proto_tree_add_uint64(tree, hf_sdnv, tvb, offset, sdnv_length, sdnv_value);
|
||||
|
||||
*value = sdnv_value;
|
||||
if (NULL != *item_ret) *item_ret = ti;
|
||||
|
||||
if (!sdnv_status) {
|
||||
if (*lenretval <= 0) {
|
||||
expert_add_info(pinfo, ti, &ei_ltp_sdnv_length);
|
||||
}
|
||||
return sdnv_length;
|
||||
return ti;
|
||||
}
|
||||
|
||||
/// Summary of a data segment tree item
|
||||
|
@ -519,7 +506,6 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int
|
|||
unsigned segment_size = 0;
|
||||
|
||||
int sdnv_length;
|
||||
int sdnv_status;
|
||||
|
||||
proto_tree *ltp_data_tree;
|
||||
proto_item *ti;
|
||||
|
@ -531,22 +517,14 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int
|
|||
/* Create a subtree for data segment and add the other fields under it */
|
||||
ltp_data_tree = proto_tree_add_subtree(ltp_tree, tvb, frame_offset, tvb_captured_length_remaining(tvb, frame_offset), ett_data_segm, NULL, "Data Segment");
|
||||
|
||||
|
||||
/* Client ID - 0 = Bundle Protocol, 1 = CCSDS LTP Service Data Aggregation */
|
||||
sdnv_status = evaluate_sdnv64(tvb, frame_offset, &sdnv_length, &client_id);
|
||||
ti = proto_tree_add_uint64_format_value(ltp_data_tree, hf_ltp_data_clid, tvb, frame_offset, sdnv_length, client_id,
|
||||
"%" PRIu64 " (%s)", client_id,
|
||||
val64_to_str_const(client_id, client_service_id_info, "Invalid"));
|
||||
if (!sdnv_status) {
|
||||
expert_add_info(pinfo, ti, &ei_ltp_sdnv_length);
|
||||
return 0;
|
||||
}
|
||||
add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_clid, &client_id, &sdnv_length);
|
||||
frame_offset += sdnv_length;
|
||||
segment_size += sdnv_length;
|
||||
|
||||
|
||||
/* data segment offset */
|
||||
if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_offset, &data_offset, &ti)) > 0) {
|
||||
add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_offset, &data_offset, &sdnv_length);
|
||||
if (sdnv_length > 0) {
|
||||
frame_offset += sdnv_length;
|
||||
segment_size += sdnv_length;
|
||||
} else {
|
||||
|
@ -554,7 +532,8 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int
|
|||
}
|
||||
|
||||
/* data segment length */
|
||||
if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_length, &data_length, &ti)) > 0) {
|
||||
add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_length, &data_length, &sdnv_length);
|
||||
if (sdnv_length > 0) {
|
||||
frame_offset += sdnv_length;
|
||||
segment_size += sdnv_length;
|
||||
|
||||
|
@ -607,7 +586,8 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int
|
|||
if (ltp_type != 0 && ltp_type < 4)
|
||||
{
|
||||
/* checkpoint serial number - 32 bits per CCSDS */
|
||||
if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_chkp, &chkp_sno, &ti)) > 0) {
|
||||
ti = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_chkp, &chkp_sno, &sdnv_length);
|
||||
if (sdnv_length > 0) {
|
||||
frame_offset += sdnv_length;
|
||||
segment_size += sdnv_length;
|
||||
|
||||
|
@ -626,7 +606,8 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int
|
|||
}
|
||||
|
||||
/* report serial number - 32 bits per CCSDS */
|
||||
if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_rpt, &rpt_sno, &ti)) > 0) {
|
||||
ti = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_rpt, &rpt_sno, &sdnv_length);
|
||||
if (sdnv_length > 0) {
|
||||
frame_offset += sdnv_length;
|
||||
segment_size += sdnv_length;
|
||||
|
||||
|
@ -734,15 +715,7 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int
|
|||
tvbuff_t *datatvb;
|
||||
|
||||
if (client_id == 2) {
|
||||
sdnv_status = evaluate_sdnv64(new_tvb, parse_offset, &sdnv_length, &sda_client_id);
|
||||
ti = proto_tree_add_uint64_format_value(root_tree, hf_ltp_data_sda_clid, new_tvb, parse_offset, sdnv_length, sda_client_id,
|
||||
"%" G_GINT64_MODIFIER "u (%s)", sda_client_id, val64_to_str_const(sda_client_id, client_service_id_info, "Invalid"));
|
||||
|
||||
if (!sdnv_status) {
|
||||
expert_add_info(pinfo, ti, &ei_ltp_sdnv_length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset+parse_offset, hf_ltp_data_sda_clid, &sda_client_id, &sdnv_length);
|
||||
parse_offset += sdnv_length;
|
||||
if (parse_offset == parse_length) {
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "CCSDS LTP SDA Protocol Error");
|
||||
|
@ -831,7 +804,7 @@ dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree,
|
|||
gint64 chkp_sno;
|
||||
guint64 upper_bound;
|
||||
guint64 lower_bound;
|
||||
int rcpt_clm_cnt;
|
||||
guint64 rcpt_clm_cnt;
|
||||
guint64 offset;
|
||||
guint64 length;
|
||||
guint64 clm_fst, clm_lst;
|
||||
|
@ -847,9 +820,9 @@ dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree,
|
|||
int segment_offset = 0;
|
||||
int gap_count = 0;
|
||||
guint64 gap_total = 0;
|
||||
int i;
|
||||
|
||||
proto_item *ltp_rpt_item;
|
||||
proto_item *ltp_rpt_clm_cnt;
|
||||
proto_item *ltp_rpt_clm_item;
|
||||
proto_item *item_rpt_sno, *item_chkp_sno;
|
||||
|
||||
|
@ -860,8 +833,7 @@ dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree,
|
|||
ltp_rpt_tree = proto_tree_add_subtree(ltp_tree, tvb, frame_offset, -1, ett_rpt_segm, <p_rpt_item, "Report Segment");
|
||||
|
||||
/* Extract the report segment info */
|
||||
rpt_sno = evaluate_sdnv_64(tvb, frame_offset, &rpt_sno_size);
|
||||
item_rpt_sno = proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_sno, tvb, frame_offset + segment_offset, rpt_sno_size, (guint64)rpt_sno);
|
||||
item_rpt_sno = add_sdnv64_to_tree(ltp_rpt_tree, tvb, pinfo, frame_offset + segment_offset, hf_ltp_rpt_sno, &rpt_sno, &rpt_sno_size);
|
||||
segment_offset += rpt_sno_size;
|
||||
if (ltp_analyze_sequence && session)
|
||||
{
|
||||
|
@ -871,8 +843,7 @@ dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree,
|
|||
ltp_ref_use(session->rpt_datas, rpt_sno, pinfo, tree_rpt_sno, hf_ltp_rpt_sno_data, -1);
|
||||
}
|
||||
|
||||
chkp_sno = evaluate_sdnv_64(tvb, frame_offset + segment_offset, &chkp_sno_size);
|
||||
item_chkp_sno = proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_chkp, tvb, frame_offset + segment_offset, chkp_sno_size, (guint64)chkp_sno);
|
||||
item_chkp_sno = add_sdnv64_to_tree(ltp_rpt_tree, tvb, pinfo, frame_offset + segment_offset, hf_ltp_rpt_chkp, &chkp_sno, &chkp_sno_size);
|
||||
segment_offset += chkp_sno_size;
|
||||
if (ltp_analyze_sequence && session)
|
||||
{
|
||||
|
@ -886,12 +857,10 @@ dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree,
|
|||
}
|
||||
}
|
||||
|
||||
upper_bound = evaluate_sdnv(tvb, frame_offset + segment_offset, &upper_bound_size);
|
||||
proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_ub, tvb, frame_offset + segment_offset, upper_bound_size, upper_bound);
|
||||
add_sdnv64_to_tree(ltp_rpt_tree, tvb, pinfo, frame_offset + segment_offset, hf_ltp_rpt_ub, &upper_bound, &upper_bound_size);
|
||||
segment_offset += upper_bound_size;
|
||||
|
||||
lower_bound = evaluate_sdnv(tvb, frame_offset + segment_offset, &lower_bound_size);
|
||||
proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_lb, tvb, frame_offset + segment_offset, lower_bound_size, lower_bound);
|
||||
add_sdnv64_to_tree(ltp_rpt_tree, tvb, pinfo, frame_offset + segment_offset, hf_ltp_rpt_lb, &lower_bound, &lower_bound_size);
|
||||
segment_offset += lower_bound_size;
|
||||
|
||||
PROTO_ITEM_SET_GENERATED(
|
||||
|
@ -942,42 +911,34 @@ dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree,
|
|||
}
|
||||
tap->corr_orig = newdata;
|
||||
|
||||
rcpt_clm_cnt = evaluate_sdnv(tvb, frame_offset + segment_offset, &rcpt_clm_cnt_size);
|
||||
if (rcpt_clm_cnt < 0){
|
||||
proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset);
|
||||
expert_add_info_format(pinfo, ltp_tree, &ei_ltp_neg_reception_claim_count,
|
||||
"Negative reception claim count: %d", rcpt_clm_cnt);
|
||||
return 0;
|
||||
}
|
||||
ltp_rpt_clm_cnt = add_sdnv64_to_tree(ltp_rpt_tree, tvb, pinfo, frame_offset + segment_offset, hf_ltp_rpt_clm_cnt, &rcpt_clm_cnt, &rcpt_clm_cnt_size);
|
||||
segment_offset += rcpt_clm_cnt_size;
|
||||
/* Each reception claim is at least 2 bytes, so if the count is larger than the
|
||||
* max number of claims we can possibly squeeze into the remaining tvbuff, then
|
||||
* the packet is malformed.
|
||||
*/
|
||||
if (rcpt_clm_cnt > tvb_captured_length_remaining(tvb, frame_offset + segment_offset) / 2) {
|
||||
proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset);
|
||||
expert_add_info_format(pinfo, ltp_tree, &ei_ltp_mal_reception_claim,
|
||||
"Reception claim count impossibly large: %d > %d", rcpt_clm_cnt,
|
||||
if (rcpt_clm_cnt > (guint64)tvb_captured_length_remaining(tvb, frame_offset + segment_offset) / 2) {
|
||||
expert_add_info_format(pinfo, ltp_rpt_clm_cnt, &ei_ltp_mal_reception_claim,
|
||||
"Reception claim count impossibly large: %" G_GINT64_MODIFIER "d > %d", rcpt_clm_cnt,
|
||||
tvb_captured_length_remaining(tvb, frame_offset + segment_offset) / 2);
|
||||
return 0;
|
||||
}
|
||||
proto_tree_add_uint(ltp_rpt_tree, hf_ltp_rpt_clm_cnt, tvb, frame_offset + segment_offset, rcpt_clm_cnt_size, rcpt_clm_cnt);
|
||||
segment_offset += rcpt_clm_cnt_size;
|
||||
|
||||
clm_lst = lower_bound - 1;
|
||||
|
||||
/* There can be multiple reception claims in the same report segment */
|
||||
for(i = 0; i<rcpt_clm_cnt; i++){
|
||||
offset = evaluate_sdnv(tvb,frame_offset + segment_offset, &offset_size);
|
||||
for(guint64 ix = 0; ix < rcpt_clm_cnt; ix++){
|
||||
/* Peek at the offset to see if there is a preceeding gap */
|
||||
tvb_get_varint(tvb, frame_offset + segment_offset, FT_VARINT_MAX_LEN, &offset, ENC_VARINT_SDNV);
|
||||
clm_fst = lower_bound + offset;
|
||||
ltp_check_reception_gap(ltp_rpt_tree, pinfo, session, clm_lst, clm_fst, &gap_count, &gap_total);
|
||||
|
||||
ltp_rpt_clm_tree = proto_tree_add_subtree(ltp_rpt_tree, tvb, frame_offset + segment_offset, -1, ett_rpt_clm, <p_rpt_clm_item, "Reception claim");
|
||||
|
||||
proto_tree_add_uint64(ltp_rpt_clm_tree, hf_ltp_rpt_clm_off, tvb, frame_offset + segment_offset, offset_size, offset);
|
||||
add_sdnv64_to_tree(ltp_rpt_clm_tree, tvb, pinfo, frame_offset + segment_offset, hf_ltp_rpt_clm_off, &offset, &offset_size);
|
||||
segment_offset += offset_size;
|
||||
|
||||
length = evaluate_sdnv(tvb,frame_offset + segment_offset, &length_size);
|
||||
proto_tree_add_uint64(ltp_rpt_clm_tree, hf_ltp_rpt_clm_len, tvb, frame_offset + segment_offset, length_size, length);
|
||||
add_sdnv64_to_tree(ltp_rpt_clm_tree, tvb, pinfo, frame_offset + segment_offset, hf_ltp_rpt_clm_len, &length, &length_size);
|
||||
segment_offset += length_size;
|
||||
|
||||
PROTO_ITEM_SET_GENERATED(
|
||||
|
@ -1030,23 +991,18 @@ dissect_report_ack_segment(proto_tree *ltp_tree, tvbuff_t *tvb, packet_info *pin
|
|||
int rpt_sno_size;
|
||||
int segment_offset = 0;
|
||||
|
||||
proto_item *item_rpt_sno;
|
||||
proto_item *ltp_rpt_ack_item, *item_rpt_sno;
|
||||
proto_tree *ltp_rpt_ack_tree;
|
||||
|
||||
/* Creating tree for the report ack segment */
|
||||
ltp_rpt_ack_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, -1,
|
||||
ett_rpt_ack_segm, <p_rpt_ack_item, "Report Ack Segment");
|
||||
|
||||
/* Extracing receipt serial number info */
|
||||
rpt_sno = evaluate_sdnv_64(tvb,frame_offset, &rpt_sno_size);
|
||||
/* XXX - verify that this does not overflow */
|
||||
item_rpt_sno = add_sdnv64_to_tree(ltp_rpt_ack_tree, tvb, pinfo, frame_offset + segment_offset, hf_ltp_rpt_ack_sno, &rpt_sno, &rpt_sno_size);
|
||||
segment_offset += rpt_sno_size;
|
||||
|
||||
if((unsigned)(frame_offset + segment_offset) > tvb_captured_length(tvb)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Creating tree for the report ack segment */
|
||||
ltp_rpt_ack_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, segment_offset,
|
||||
ett_rpt_ack_segm, NULL, "Report Ack Segment");
|
||||
|
||||
item_rpt_sno = proto_tree_add_uint64(ltp_rpt_ack_tree, hf_ltp_rpt_ack_sno, tvb, frame_offset,rpt_sno_size, (guint64)rpt_sno);
|
||||
proto_item_set_end(ltp_rpt_ack_item, tvb, frame_offset + segment_offset);
|
||||
|
||||
if (ltp_analyze_sequence && session)
|
||||
{
|
||||
|
@ -1079,97 +1035,60 @@ dissect_cancel_segment(proto_tree * ltp_tree, tvbuff_t *tvb, int frame_offset, l
|
|||
|
||||
|
||||
static int
|
||||
dissect_header_extn(proto_tree *ltp_tree, tvbuff_t *tvb,int frame_offset,int hdr_extn_cnt){
|
||||
guint8 extn_type[LTP_MAX_HDR_EXTN];
|
||||
gint64 length[LTP_MAX_HDR_EXTN];
|
||||
dissect_header_extn(proto_tree *ltp_tree, tvbuff_t *tvb, packet_info *pinfo, int frame_offset,int hdr_extn_cnt){
|
||||
gint64 length;
|
||||
int length_size;
|
||||
|
||||
int length_size[LTP_MAX_HDR_EXTN];
|
||||
|
||||
int i;
|
||||
int extn_offset = 0;
|
||||
|
||||
proto_item *ltp_hdr_extn_item;
|
||||
proto_tree *ltp_hdr_extn_tree;
|
||||
|
||||
/* There can be more than one header extensions */
|
||||
for(i = 0; i < hdr_extn_cnt; i++){
|
||||
extn_type[i] = tvb_get_guint8(tvb,frame_offset);
|
||||
extn_offset++;
|
||||
ltp_hdr_extn_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, -1, ett_hdr_extn, <p_hdr_extn_item, "Header Extension");
|
||||
|
||||
length[i] = evaluate_sdnv_64(tvb,frame_offset+1,&length_size[i]);
|
||||
if((guint64)(frame_offset + extn_offset + length_size[i] + length[i]) >= (guint64)tvb_captured_length(tvb)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
extn_offset += length_size[i];
|
||||
for(int ix = 0; ix < hdr_extn_cnt; ix++){
|
||||
/* From RFC-5326, the total length of the Header Extension Tree will be length of the following:
|
||||
a) Extension type length (1 byte)
|
||||
b) The length of the 'length' field (as defined by the SDNV which handles dynamic size)
|
||||
c) The length of the value field which is the decoded length */
|
||||
extn_offset += (int)length[i];
|
||||
proto_tree_add_item(ltp_hdr_extn_tree, hf_ltp_hdr_extn_tag, tvb, frame_offset + extn_offset, 1, ENC_NA);
|
||||
extn_offset += 1;
|
||||
|
||||
add_sdnv64_to_tree(ltp_hdr_extn_tree, tvb, pinfo, frame_offset + extn_offset, hf_ltp_hdr_extn_len, &length, &length_size);
|
||||
extn_offset += length_size;
|
||||
|
||||
proto_tree_add_item(ltp_hdr_extn_tree, hf_ltp_hdr_extn_val, tvb, frame_offset + extn_offset, (int)length, ENC_NA);
|
||||
extn_offset += (int)length;
|
||||
}
|
||||
ltp_hdr_extn_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, extn_offset, ett_hdr_extn, NULL, "Header Extension");
|
||||
|
||||
for(i = 0; i < hdr_extn_cnt; i++){
|
||||
proto_tree_add_uint_format_value(ltp_hdr_extn_tree, hf_ltp_hdr_extn_tag, tvb, frame_offset, 1, extn_type[i], "%x (%s)", extn_type[i], val_to_str_const(extn_type[i],extn_tag_codes,"Unassigned/Reserved"));
|
||||
frame_offset += 1;
|
||||
|
||||
proto_tree_add_uint64_format(ltp_hdr_extn_tree, hf_ltp_hdr_extn_len, tvb, frame_offset, length_size[i],length[i], "Length [%d]: %"PRId64,i+1,length[i]);
|
||||
frame_offset += length_size[i];
|
||||
|
||||
proto_tree_add_item (ltp_hdr_extn_tree, hf_ltp_hdr_extn_val, tvb, frame_offset, (int)length[i], ENC_NA);
|
||||
frame_offset += (int)length[i];
|
||||
}
|
||||
proto_item_set_end(ltp_hdr_extn_item, tvb, frame_offset + extn_offset);
|
||||
return extn_offset;
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_trailer_extn(proto_tree *ltp_tree, tvbuff_t *tvb,int frame_offset,int trl_extn_cnt){
|
||||
guint8 extn_type[LTP_MAX_TRL_EXTN];
|
||||
gint64 length[LTP_MAX_TRL_EXTN];
|
||||
dissect_trailer_extn(proto_tree *ltp_tree, tvbuff_t *tvb, packet_info *pinfo, int frame_offset,int trl_extn_cnt){
|
||||
gint64 length;
|
||||
int length_size;
|
||||
|
||||
int length_size[LTP_MAX_TRL_EXTN];
|
||||
|
||||
int i;
|
||||
int extn_offset = 0;
|
||||
|
||||
proto_item *ltp_trl_extn_item;
|
||||
proto_tree *ltp_trl_extn_tree;
|
||||
|
||||
DISSECTOR_ASSERT(trl_extn_cnt < LTP_MAX_TRL_EXTN);
|
||||
ltp_trl_extn_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, -1, ett_trl_extn, <p_trl_extn_item, "Trailer Extension");
|
||||
|
||||
for(i = 0; i < trl_extn_cnt; i++){
|
||||
extn_type[i] = tvb_get_guint8(tvb,frame_offset);
|
||||
extn_offset++;
|
||||
|
||||
if((unsigned)(frame_offset + extn_offset) >= tvb_captured_length(tvb)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
length[i] = evaluate_sdnv_64(tvb,frame_offset+1,&length_size[i]);
|
||||
extn_offset += length_size[i];
|
||||
|
||||
if((guint64)(frame_offset + extn_offset + length_size[i] + length[i]) >= tvb_captured_length(tvb)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* From RFC-5326, the total length of the Trailer Extension Tree will be length of the following:
|
||||
a) Extension type length (1 byte)
|
||||
b) The length of the 'length' field (as defined by the SDNV which handles dynamic size)
|
||||
c) The length of the value field which is the decoded length */
|
||||
extn_offset += (int)length[i];
|
||||
}
|
||||
|
||||
ltp_trl_extn_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, extn_offset, ett_trl_extn, NULL, "Trailer Extension");
|
||||
|
||||
for(i = 0; i < trl_extn_cnt; i++){
|
||||
proto_tree_add_uint_format_value(ltp_trl_extn_tree, hf_ltp_trl_extn_tag, tvb, frame_offset, 1, extn_type[i], "%x (%s)", extn_type[i], val_to_str_const(extn_type[i],extn_tag_codes,"Unassigned/Reserved"));
|
||||
for(int ix = 0; ix < trl_extn_cnt; ix++){
|
||||
proto_tree_add_item(ltp_trl_extn_tree, hf_ltp_trl_extn_tag, tvb, frame_offset + extn_offset, 1, ENC_NA);
|
||||
frame_offset += 1;
|
||||
|
||||
proto_tree_add_uint64_format(ltp_trl_extn_tree, hf_ltp_trl_extn_len, tvb, frame_offset, length_size[i], length[i], "Length [%d]: %"PRId64,i+1,length[i]);
|
||||
frame_offset += length_size[i];
|
||||
add_sdnv64_to_tree(ltp_trl_extn_tree, tvb, pinfo, frame_offset + extn_offset, hf_ltp_hdr_extn_len, &length, &length_size);
|
||||
frame_offset += length_size;
|
||||
|
||||
proto_tree_add_item (ltp_trl_extn_tree, hf_ltp_trl_extn_val, tvb, frame_offset, (int)length[i], ENC_NA);
|
||||
frame_offset += (int)length[i];
|
||||
proto_tree_add_item(ltp_trl_extn_tree, hf_ltp_trl_extn_val, tvb, frame_offset + extn_offset, (int)length, ENC_NA);
|
||||
frame_offset += (int)length;
|
||||
}
|
||||
|
||||
proto_item_set_end(ltp_trl_extn_item, tvb, frame_offset + extn_offset);
|
||||
return extn_offset;
|
||||
}
|
||||
|
||||
|
@ -1224,21 +1143,11 @@ dissect_ltp_segment(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
|
|||
ltp_session_tree = proto_tree_add_subtree(ltp_header_tree, tvb, frame_offset, 0, ett_hdr_session, NULL, "Session ID");
|
||||
ltp_session_item = proto_tree_get_parent(ltp_session_tree);
|
||||
|
||||
sess_id.orig_eng_id = evaluate_sdnv_64(tvb,frame_offset,&engine_id_size);
|
||||
proto_tree_add_uint64(ltp_session_tree,hf_ltp_session_orig,tvb,frame_offset,engine_id_size,sess_id.orig_eng_id);
|
||||
add_sdnv64_to_tree(ltp_session_tree, tvb, pinfo, frame_offset, hf_ltp_session_orig, &sess_id.orig_eng_id, &engine_id_size);
|
||||
frame_offset += engine_id_size;
|
||||
if((unsigned)frame_offset >= tvb_captured_length(tvb)){
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sess_id.sess_num = evaluate_sdnv_64(tvb,frame_offset,&session_num_size);
|
||||
proto_tree_add_uint64(ltp_session_tree,hf_ltp_session_no, tvb, frame_offset,session_num_size,sess_id.sess_num);
|
||||
add_sdnv64_to_tree(ltp_session_tree, tvb, pinfo, frame_offset, hf_ltp_session_no, &sess_id.sess_num, &session_num_size);
|
||||
frame_offset += session_num_size;
|
||||
if((unsigned)frame_offset >= tvb_captured_length(tvb)){
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
proto_item_set_end(ltp_session_item, tvb, frame_offset);
|
||||
tap->sess_id = sess_id;
|
||||
|
@ -1303,33 +1212,12 @@ dissect_ltp_segment(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
|
|||
col_add_fstr(pinfo->cinfo, COL_INFO, "Session %s, %s", sess_name, val_to_str_const(ltp_type,ltp_type_col_info,"Protocol Error"));
|
||||
|
||||
/* Check if there are any header extensions */
|
||||
if(hdr_extn_cnt > 0){
|
||||
int hdr_extn_offset;
|
||||
|
||||
if((unsigned)frame_offset >= tvb_captured_length(tvb)){
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdr_extn_offset = dissect_header_extn(ltp_tree, tvb, frame_offset,hdr_extn_cnt);
|
||||
if(hdr_extn_offset == 0){
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
|
||||
return 0;
|
||||
}
|
||||
if(hdr_extn_cnt > 0)
|
||||
{
|
||||
int hdr_extn_offset = dissect_header_extn(ltp_tree, tvb, pinfo, frame_offset,hdr_extn_cnt);
|
||||
frame_offset += hdr_extn_offset;
|
||||
}
|
||||
|
||||
if((unsigned)frame_offset > tvb_captured_length(tvb)){
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
|
||||
return 0;
|
||||
}
|
||||
else if((unsigned)frame_offset == tvb_captured_length(tvb)){
|
||||
if(ltp_type != 13 && ltp_type != 15){
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call sub routines to handle the segment content*/
|
||||
if((ltp_type >= 0) && (ltp_type < 8)){
|
||||
segment_offset = dissect_data_segment(ltp_tree,tvb,pinfo,frame_offset,ltp_type, &data_len, tap);
|
||||
|
@ -1366,17 +1254,9 @@ dissect_ltp_segment(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *t
|
|||
|
||||
/* Check to see if there are any trailer extensions */
|
||||
const int trl_start = frame_offset;
|
||||
int trl_length = 0;
|
||||
if(trl_extn_cnt > 0){
|
||||
if((unsigned)frame_offset >= tvb_captured_length(tvb)){
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
|
||||
return 0;
|
||||
}
|
||||
trl_length = dissect_trailer_extn(ltp_tree, tvb, frame_offset,trl_extn_cnt);
|
||||
if(0 == trl_length) {
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
|
||||
return 0;
|
||||
}
|
||||
if(trl_extn_cnt > 0)
|
||||
{
|
||||
int trl_length = dissect_trailer_extn(ltp_tree, tvb, pinfo, frame_offset,trl_extn_cnt);
|
||||
frame_offset += trl_length;
|
||||
}
|
||||
|
||||
|
@ -1717,7 +1597,7 @@ proto_register_ltp(void)
|
|||
},
|
||||
{&hf_ltp_data_clid,
|
||||
{"Client service ID","ltp.data.client.id",
|
||||
FT_UINT64,BASE_DEC,NULL, 0x0, NULL, HFILL}
|
||||
FT_UINT64,BASE_DEC | BASE_VAL64_STRING, VALS64(client_service_id_info), 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_ltp_data_offset,
|
||||
{"Offset","ltp.data.offset",
|
||||
|
@ -1818,7 +1698,7 @@ proto_register_ltp(void)
|
|||
},
|
||||
{&hf_ltp_rpt_clm_cnt,
|
||||
{"Reception claim count","ltp.rpt.clm.cnt",
|
||||
FT_UINT8,BASE_DEC,NULL, 0x0, NULL, HFILL}
|
||||
FT_UINT64,BASE_DEC,NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_ltp_rpt_clm_off,
|
||||
{"Offset","ltp.rpt.clm.off",
|
||||
|
@ -1876,7 +1756,7 @@ proto_register_ltp(void)
|
|||
},
|
||||
{&hf_ltp_hdr_extn_tag,
|
||||
{"Extension tag","ltp.hdr.extn.tag",
|
||||
FT_UINT8,BASE_HEX,NULL, 0x0, NULL, HFILL}
|
||||
FT_UINT8,BASE_HEX,VALS(extn_tag_codes), 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_ltp_hdr_extn_len,
|
||||
{"Length","ltp.hdr.extn.len",
|
||||
|
@ -1888,7 +1768,7 @@ proto_register_ltp(void)
|
|||
},
|
||||
{&hf_ltp_trl_extn_tag,
|
||||
{"Extension tag","ltp.trl.extn.tag",
|
||||
FT_UINT8,BASE_HEX,NULL, 0x0, NULL, HFILL}
|
||||
FT_UINT8,BASE_HEX,VALS(extn_tag_codes), 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_ltp_trl_extn_len,
|
||||
{"Length","ltp.trl.extn.len",
|
||||
|
@ -1973,7 +1853,6 @@ proto_register_ltp(void)
|
|||
};
|
||||
|
||||
static ei_register_info ei[] = {
|
||||
{ &ei_ltp_neg_reception_claim_count, { "ltp.neg_reception_claim_count", PI_UNDECODED, PI_ERROR, "Negative reception claim count", EXPFILL }},
|
||||
{ &ei_ltp_mal_reception_claim, { "ltp.mal_reception_claim", PI_MALFORMED, PI_ERROR, "Reception claim count impossibly large", EXPFILL }},
|
||||
{ &ei_ltp_sdnv_length, { "ltp.sdnv_length_invalid", PI_PROTOCOL, PI_ERROR, "SDNV length error", EXPFILL }},
|
||||
{ &ei_ltp_sno_larger_than_ccsds, { "ltp.serial_number_too_large", PI_PROTOCOL, PI_WARN, "Serial number larger than CCSDS specification", EXPFILL }},
|
||||
|
|
|
@ -282,7 +282,7 @@ static hf_register_info hf_tcpcl[] = {
|
|||
{&hf_tcpclv3_xfer_id, {"Implied Transfer ID", "tcpcl.xfer_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_tcpclv3_data_segment_length,
|
||||
{"Segment Length", "tcpcl.data.length",
|
||||
FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_tcpclv3_data_segment_data,
|
||||
{"Segment Data", "tcpcl.data",
|
||||
|
@ -310,7 +310,7 @@ static hf_register_info hf_tcpcl[] = {
|
|||
},
|
||||
{&hf_tcpclv3_ack_length,
|
||||
{"Ack Length", "tcpcl.ack.length",
|
||||
FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_tcpclv3_chdr_flags,
|
||||
{"Flags", "tcpcl.contact_hdr.flags",
|
||||
|
@ -338,7 +338,7 @@ static hf_register_info hf_tcpcl[] = {
|
|||
},
|
||||
{&hf_tcpclv3_chdr_local_eid_length,
|
||||
{"Local EID Length", "tcpcl.contact_hdr.local_eid_length",
|
||||
FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
|
||||
{&hf_tcpclv4_chdr_flags, {"Contact Flags", "tcpcl.v4.chdr.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
|
||||
|
@ -532,6 +532,7 @@ static expert_field ei_invalid_version = EI_INIT;
|
|||
static expert_field ei_mismatch_version = EI_INIT;
|
||||
static expert_field ei_chdr_duplicate = EI_INIT;
|
||||
|
||||
static expert_field ei_tcpclv3_eid_length = EI_INIT;
|
||||
static expert_field ei_tcpclv3_invalid_msg_type = EI_INIT;
|
||||
static expert_field ei_tcpclv3_data_flags = EI_INIT;
|
||||
static expert_field ei_tcpclv3_segment_length = EI_INIT;
|
||||
|
@ -564,6 +565,7 @@ static ei_register_info ei_tcpcl[] = {
|
|||
{&ei_mismatch_version, { "tcpcl.mismatch_contact_version", PI_PROTOCOL, PI_ERROR, "Protocol version mismatch", EXPFILL}},
|
||||
{&ei_chdr_duplicate, { "tcpcl.contact_duplicate", PI_SEQUENCE, PI_ERROR, "Duplicate Contact Header", EXPFILL}},
|
||||
|
||||
{&ei_tcpclv3_eid_length, { "tcpcl.eid_length_invalid", PI_PROTOCOL, PI_ERROR, "Invalid EID Length", EXPFILL }},
|
||||
{&ei_tcpclv3_invalid_msg_type, { "tcpcl.unknown_message_type", PI_UNDECODED, PI_ERROR, "Message type is unknown", EXPFILL}},
|
||||
{&ei_tcpclv3_data_flags, { "tcpcl.data.flags.invalid", PI_PROTOCOL, PI_WARN, "Invalid TCP CL Data Segment Flags", EXPFILL }},
|
||||
{&ei_tcpclv3_segment_length, { "tcpcl.data.length.invalid", PI_PROTOCOL, PI_ERROR, "Invalid Data Length", EXPFILL }},
|
||||
|
@ -614,6 +616,10 @@ static const fragment_items xfer_frag_items = {
|
|||
"Transfer fragments"
|
||||
};
|
||||
|
||||
static guint tvb_get_sdnv(tvbuff_t *tvb, guint offset, guint64 *value) {
|
||||
return tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, value, ENC_VARINT_SDNV);
|
||||
}
|
||||
|
||||
static void tcpcl_frame_loc_init(tcpcl_frame_loc_t *loc, const packet_info *pinfo, tvbuff_t *tvb, const gint offset) {
|
||||
loc->frame_num = pinfo->num;
|
||||
// This is a messy way to determine the index,
|
||||
|
@ -1164,7 +1170,8 @@ get_v3_msg_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset,
|
|||
tcpcl_dissect_ctx_t *ctx _U_)
|
||||
{
|
||||
const int orig_offset = offset;
|
||||
int len, bytecount;
|
||||
guint64 len;
|
||||
guint bytecount;
|
||||
guint8 conv_hdr = tvb_get_guint8(tvb, offset);
|
||||
offset += 1;
|
||||
|
||||
|
@ -1172,8 +1179,8 @@ get_v3_msg_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset,
|
|||
{
|
||||
case TCPCLV3_DATA_SEGMENT:
|
||||
/* get length from sdnv */
|
||||
len = evaluate_sdnv(tvb, offset, &bytecount);
|
||||
if (len < 0)
|
||||
bytecount = tvb_get_sdnv(tvb, offset, &len);
|
||||
if (bytecount == 0)
|
||||
return 0;
|
||||
|
||||
offset += bytecount+len;
|
||||
|
@ -1181,8 +1188,8 @@ get_v3_msg_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset,
|
|||
|
||||
case TCPCLV3_ACK_SEGMENT:
|
||||
/* get length from sdnv */
|
||||
len = evaluate_sdnv(tvb, offset, &bytecount);
|
||||
if (len < 0)
|
||||
bytecount = tvb_get_sdnv(tvb, offset, &len);
|
||||
if (bytecount == 0)
|
||||
return 0;
|
||||
|
||||
offset += bytecount;
|
||||
|
@ -1203,8 +1210,8 @@ get_v3_msg_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset,
|
|||
|
||||
case TCPCLV3_LENGTH:
|
||||
/* get length from sdnv */
|
||||
len = evaluate_sdnv(tvb, offset, &bytecount);
|
||||
if (len < 0)
|
||||
bytecount = tvb_get_sdnv(tvb, offset, &len);
|
||||
if (bytecount == 0)
|
||||
return 0;
|
||||
offset += bytecount;
|
||||
break;
|
||||
|
@ -1222,7 +1229,8 @@ dissect_v3_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|||
const char *msgtype_name;
|
||||
guint8 refuse_bundle_hdr;
|
||||
int offset = 0;
|
||||
int sdnv_length, segment_length;
|
||||
gint sdnv_length;
|
||||
guint64 segment_length;
|
||||
proto_item *conv_item, *sub_item;
|
||||
proto_tree *conv_tree, *sub_tree;
|
||||
guint64 *xfer_id = NULL;
|
||||
|
@ -1248,19 +1256,20 @@ dissect_v3_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|||
ett_tcpclv3_data_procflags, v3_data_procflags,
|
||||
ENC_BIG_ENDIAN
|
||||
);
|
||||
offset += 1;
|
||||
|
||||
/* Only Start and End flags (bits 0 & 1) are valid in Data Segment */
|
||||
if ((conv_hdr & ~(TCPCLV3_TYPE_MASK | TCPCLV3_DATA_FLAGS)) != 0) {
|
||||
expert_add_info(pinfo, item_flags, &ei_tcpclv3_data_flags);
|
||||
}
|
||||
|
||||
segment_length = evaluate_sdnv(tvb, 1, &sdnv_length);
|
||||
sub_item = proto_tree_add_int(conv_tree, hf_tcpclv3_data_segment_length, tvb, 1, sdnv_length, segment_length);
|
||||
if (segment_length < 0) {
|
||||
sub_item = proto_tree_add_item_ret_varint(conv_tree, hf_tcpclv3_data_segment_length, tvb, offset, -1, ENC_VARINT_SDNV, &segment_length, &sdnv_length);
|
||||
if (sdnv_length == 0) {
|
||||
expert_add_info(pinfo, sub_item, &ei_tcpclv3_segment_length);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
offset += 1 + sdnv_length;
|
||||
offset += sdnv_length;
|
||||
const gint data_len_clamp = get_clamped_length(segment_length);
|
||||
|
||||
// implied transfer ID
|
||||
xfer_id = wmem_map_lookup(ctx->tx_peer->frame_loc_to_transfer, ctx->cur_loc);
|
||||
|
@ -1277,7 +1286,7 @@ dissect_v3_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|||
item_xfer_id = proto_tree_add_uint64(conv_tree, hf_tcpclv3_xfer_id, tvb, 0, 0, *xfer_id);
|
||||
proto_item_set_generated(item_xfer_id);
|
||||
|
||||
proto_tree_add_item(conv_tree, hf_tcpclv3_data_segment_data, tvb, offset, segment_length, ENC_NA);
|
||||
proto_tree_add_item(conv_tree, hf_tcpclv3_data_segment_data, tvb, offset, data_len_clamp, ENC_NA);
|
||||
|
||||
if (tcpcl_analyze_sequence) {
|
||||
transfer_add_segment(ctx, *xfer_id, (conv_hdr & TCPCLV3_DATA_FLAGS), segment_length, pinfo, tvb, conv_tree, conv_item, item_flags);
|
||||
|
@ -1290,7 +1299,7 @@ dissect_v3_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|||
&xfer_reassembly_table,
|
||||
tvb, offset,
|
||||
pinfo, 0, xfer_id,
|
||||
segment_length,
|
||||
data_len_clamp,
|
||||
!(conv_hdr & TCPCLV3_DATA_END_FLAG)
|
||||
);
|
||||
ctx->xferload = process_reassembled_data(
|
||||
|
@ -1310,9 +1319,8 @@ dissect_v3_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|||
/*No valid flags*/
|
||||
offset += 1;
|
||||
|
||||
segment_length = evaluate_sdnv(tvb, offset, &sdnv_length);
|
||||
sub_item = proto_tree_add_int(conv_tree, hf_tcpclv3_ack_length, tvb, offset, sdnv_length, segment_length);
|
||||
if (segment_length < 0) {
|
||||
sub_item = proto_tree_add_item_ret_varint(conv_tree, hf_tcpclv3_ack_length, tvb, offset, -1, ENC_VARINT_SDNV, &segment_length, &sdnv_length);
|
||||
if (sdnv_length == 0) {
|
||||
expert_add_info(pinfo, sub_item, &ei_tcpclv3_ack_length);
|
||||
} else {
|
||||
offset += sdnv_length;
|
||||
|
@ -1889,10 +1897,10 @@ static guint get_message_len(packet_info *pinfo, tvbuff_t *tvb, int ext_offset,
|
|||
guint8 version = tvb_get_guint8(tvb, offset);
|
||||
offset += 1;
|
||||
if (version == 3) {
|
||||
offset += 3;
|
||||
int bytecount;
|
||||
int len = evaluate_sdnv(tvb, offset, &bytecount);
|
||||
offset += len + 1;
|
||||
offset += 3; // flags + keepalive
|
||||
guint64 len;
|
||||
guint bytecount = tvb_get_sdnv(tvb, offset, &len);
|
||||
offset += bytecount+len;
|
||||
}
|
||||
else if (version == 4) {
|
||||
offset += 1;
|
||||
|
@ -1993,20 +2001,20 @@ static gint dissect_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|||
offset += 2;
|
||||
|
||||
/*
|
||||
* New format Contact header has length field followed by Bundle Header.
|
||||
* New format Contact header has length field followed by EID.
|
||||
*/
|
||||
guint64 eid_length;
|
||||
int sdnv_length;
|
||||
expert_field *ei_bundle_sdnv_length;
|
||||
int eid_length = evaluate_sdnv_ei(tvb, offset, &sdnv_length, &ei_bundle_sdnv_length);
|
||||
proto_item *item_len = proto_tree_add_int(tree_chdr, hf_tcpclv3_chdr_local_eid_length, tvb, offset, sdnv_length, eid_length);
|
||||
offset += sdnv_length;
|
||||
if (ei_bundle_sdnv_length) {
|
||||
expert_add_info(pinfo, item_len, ei_bundle_sdnv_length);
|
||||
return offset;
|
||||
proto_item *sub_item = proto_tree_add_item_ret_varint(tree_chdr, hf_tcpclv3_chdr_local_eid_length, tvb, offset, -1, ENC_VARINT_SDNV, &eid_length, &sdnv_length);
|
||||
if (sdnv_length == 0) {
|
||||
expert_add_info(pinfo, sub_item, &ei_tcpclv3_eid_length);
|
||||
return 0;
|
||||
}
|
||||
offset += sdnv_length;
|
||||
const gint eid_len_clamp = get_clamped_length(eid_length);
|
||||
|
||||
proto_tree_add_item(tree_chdr, hf_tcpclv3_chdr_local_eid, tvb, offset, eid_length, ENC_NA|ENC_ASCII);
|
||||
offset += eid_length;
|
||||
proto_tree_add_item(tree_chdr, hf_tcpclv3_chdr_local_eid, tvb, offset, eid_len_clamp, ENC_NA|ENC_ASCII);
|
||||
offset += eid_len_clamp;
|
||||
|
||||
// assumed parameters
|
||||
ctx->tx_peer->segment_mru = G_MAXUINT64;
|
||||
|
|
|
@ -157,6 +157,7 @@ static ws_enum_t all_enums[] = {
|
|||
ENUM(ENC_VARINT_PROTOBUF),
|
||||
ENUM(ENC_VARINT_QUIC),
|
||||
ENUM(ENC_VARINT_ZIGZAG),
|
||||
ENUM(ENC_VARINT_SDNV),
|
||||
ENUM(ENC_WINDOWS_1250),
|
||||
ENUM(ENC_WINDOWS_1251),
|
||||
ENUM(ENC_WINDOWS_1252),
|
||||
|
|
12
epan/proto.c
12
epan/proto.c
|
@ -3199,7 +3199,7 @@ proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
|||
proto_tree_set_uint(new_fi, value);
|
||||
|
||||
new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
|
||||
new_fi->flags |= FI_VARINT;
|
||||
}
|
||||
return proto_tree_add_node(tree, new_fi);
|
||||
|
@ -3491,7 +3491,7 @@ proto_tree_add_item_ret_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
|||
proto_tree_set_uint64(new_fi, value);
|
||||
|
||||
new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
|
||||
new_fi->flags |= FI_VARINT;
|
||||
}
|
||||
|
||||
|
@ -3551,7 +3551,7 @@ proto_tree_add_item_ret_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
|||
proto_tree_set_int64(new_fi, value);
|
||||
|
||||
new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
|
||||
if (encoding & (ENC_VARINT_PROTOBUF | ENC_VARINT_ZIGZAG)) {
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
|
||||
new_fi->flags |= FI_VARINT;
|
||||
}
|
||||
|
||||
|
@ -3608,7 +3608,7 @@ proto_tree_add_item_ret_varint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
|||
proto_tree_set_uint64(new_fi, value);
|
||||
|
||||
new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
|
||||
new_fi->flags |= FI_VARINT;
|
||||
}
|
||||
|
||||
|
@ -6062,7 +6062,7 @@ get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint
|
|||
* of the string", and if the tvbuff if short, we just
|
||||
* throw an exception.
|
||||
*
|
||||
* For ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARIANT_ZIGZAG, it means "find the end of the string",
|
||||
* For ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARIANT_ZIGZAG|ENC_VARINT_SDNV, it means "find the end of the string",
|
||||
* and if the tvbuff if short, we just throw an exception.
|
||||
*
|
||||
* It's not valid for any other type of field. For those
|
||||
|
@ -6073,7 +6073,7 @@ get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint
|
|||
* Length would run past the end of the packet.
|
||||
*/
|
||||
if ((IS_FT_INT(hfinfo->type)) || (IS_FT_UINT(hfinfo->type))) {
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
|
||||
if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
|
||||
/*
|
||||
* Leave the length as -1, so our caller knows
|
||||
* it was -1.
|
||||
|
|
|
@ -639,8 +639,13 @@ void proto_report_dissector_bug(const char *format, ...)
|
|||
* See https://developers.google.com/protocol-buffers/docs/encoding?csw=1#types
|
||||
*/
|
||||
#define ENC_VARINT_ZIGZAG 0x00000008
|
||||
/*
|
||||
* Decodes a variable-length integer used in DTN protocols
|
||||
* See https://www.rfc-editor.org/rfc/rfc6256.html
|
||||
*/
|
||||
#define ENC_VARINT_SDNV 0x00000010
|
||||
|
||||
#define ENC_VARINT_MASK (ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARINT_ZIGZAG)
|
||||
#define ENC_VARINT_MASK (ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)
|
||||
|
||||
/* Values for header_field_info.display */
|
||||
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "tvbuff.h"
|
||||
#include "proto.h"
|
||||
#include "exceptions.h"
|
||||
#include "wsutil/pint.h"
|
||||
|
||||
#include <ws_diag_control.h>
|
||||
|
||||
gboolean failed = FALSE;
|
||||
|
||||
typedef struct {
|
||||
|
@ -605,6 +608,94 @@ run_tests(void)
|
|||
tvb_free_chain(tvb_parent); /* should free all tvb's and associated data */
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Raw bytes
|
||||
gint enc_len;
|
||||
const guint8 *enc;
|
||||
// Varint parameters
|
||||
int encoding;
|
||||
int maxlen;
|
||||
// Results
|
||||
unsigned long expect_except;
|
||||
guint64 expect_val;
|
||||
guint expect_len;
|
||||
} varint_test_s;
|
||||
|
||||
DIAG_OFF_PEDANTIC
|
||||
varint_test_s varint[] = {
|
||||
{0, (const guint8 *)"", 0, FT_VARINT_MAX_LEN, DissectorError, 0, 0}, // no encoding specified
|
||||
// ENC_VARINT_PROTOBUF
|
||||
{0, (const guint8 *)"", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, ReportedBoundsError, 0, 0},
|
||||
{1, (const guint8 *)"\x00", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 0, 1},
|
||||
{1, (const guint8 *)"\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 1, 1},
|
||||
{1, (const guint8 *)"\x7f", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 0x7f, 1},
|
||||
{2, (const guint8 *)"\x80\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 1ul<<7, 2},
|
||||
{1, (const guint8 *)"\x80", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, ReportedBoundsError, 0, 0}, // truncated data
|
||||
{2, (const guint8 *)"\x80\x01", ENC_VARINT_PROTOBUF, 1, 0, 0, 0}, // truncated read
|
||||
{5, (const guint8 *)"\x80\x80\x80\x80\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 1ul<<28, 5},
|
||||
{10, (const guint8 *)"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 1ul<<63, 10},
|
||||
{10, (const guint8 *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 0xfffffffffffffffful, 10},
|
||||
{10, (const guint8 *)"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x02", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 0, 10}, // overflow
|
||||
// ENC_VARINT_SDNV
|
||||
{0, (const guint8 *)"", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, ReportedBoundsError, 0, 0},
|
||||
{1, (const guint8 *)"\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 0, 1},
|
||||
{1, (const guint8 *)"\x01", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 1, 1},
|
||||
{1, (const guint8 *)"\x7f", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 0x7f, 1},
|
||||
{2, (const guint8 *)"\x81\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 1ul<<7, 2},
|
||||
{1, (const guint8 *)"\x81", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, ReportedBoundsError, 1, 0}, // truncated data
|
||||
{2, (const guint8 *)"\x81\x00", ENC_VARINT_SDNV, 1, 0, 1, 0}, // truncated read
|
||||
{5, (const guint8 *)"\x81\x80\x80\x80\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 1ul<<28, 5},
|
||||
{10, (const guint8 *)"\x81\x80\x80\x80\x80\x80\x80\x80\x80\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 1ul<<63, 10},
|
||||
{10, (const guint8 *)"\x81\xff\xff\xff\xff\xff\xff\xff\xff\x7f", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 0xfffffffffffffffful, 10},
|
||||
{10, (const guint8 *)"\x82\x80\x80\x80\x80\x80\x80\x80\x80\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 1ul<<57, 0}, // overflow
|
||||
};
|
||||
DIAG_ON_PEDANTIC
|
||||
|
||||
static void
|
||||
varint_tests(void)
|
||||
{
|
||||
tvbuff_t *tvb_parent, *tvb;
|
||||
tvb_parent = tvb_new_real_data((const guint8*)"", 0, 0);
|
||||
|
||||
for (size_t ix = 0; ix < (sizeof(varint) / sizeof(varint_test_s)); ++ix) {
|
||||
const varint_test_s *vit = &varint[ix];
|
||||
tvb = tvb_new_child_real_data(tvb_parent, vit->enc, vit->enc_len, vit->enc_len);
|
||||
|
||||
unsigned long got_ex = 0;
|
||||
guint64 got_val = 0;
|
||||
guint got_len = 0;
|
||||
TRY {
|
||||
got_len = tvb_get_varint(tvb, 0, vit->maxlen, &got_val, vit->encoding);
|
||||
}
|
||||
CATCH_ALL {
|
||||
got_ex = exc->except_id.except_code;
|
||||
}
|
||||
ENDTRY;
|
||||
if (got_ex != vit->expect_except) {
|
||||
printf("Failed varint #%zu with exception=%d while expected exception=%d\n",
|
||||
ix, got_ex, vit->expect_except);
|
||||
failed = TRUE;
|
||||
continue;
|
||||
}
|
||||
if (got_val != vit->expect_val) {
|
||||
printf("Failed varint #%zu value=%" PRIu64 " while expected value=%" PRIu64 "\n",
|
||||
ix, got_val, vit->expect_val);
|
||||
failed = TRUE;
|
||||
continue;
|
||||
}
|
||||
if (got_len != vit->expect_len) {
|
||||
printf("Failed varint #%zu length=%u while expected length=%u\n",
|
||||
ix, got_len, vit->expect_len);
|
||||
failed = TRUE;
|
||||
continue;
|
||||
}
|
||||
printf("Passed varint #%zu\n", ix);
|
||||
}
|
||||
|
||||
tvb_free_chain(tvb_parent); /* should free all tvb's and associated data */
|
||||
}
|
||||
|
||||
/* Note: valgrind can be used to check for tvbuff memory leaks */
|
||||
int
|
||||
main(void)
|
||||
|
@ -615,6 +706,7 @@ main(void)
|
|||
|
||||
except_init();
|
||||
run_tests();
|
||||
varint_tests();
|
||||
except_deinit();
|
||||
exit(failed?1:0);
|
||||
}
|
||||
|
|
|
@ -4563,6 +4563,29 @@ tvb_get_varint(tvbuff_t *tvb, guint offset, guint maxlen, guint64 *value, const
|
|||
break;
|
||||
}
|
||||
|
||||
case ENC_VARINT_SDNV:
|
||||
{
|
||||
/* Decodes similar to protobuf but in MSByte order */
|
||||
guint i;
|
||||
guint64 b; /* current byte */
|
||||
|
||||
for (i = 0; ((i < FT_VARINT_MAX_LEN) && (i < maxlen)); ++i) {
|
||||
b = tvb_get_guint8(tvb, offset++);
|
||||
if ((i == 9) && (*value >= 1ul<<(64-7))) {
|
||||
// guaranteed overflow, not valid SDNV
|
||||
return 0;
|
||||
}
|
||||
*value <<= 7;
|
||||
*value |= (b & 0x7F); /* add lower 7 bits to val */
|
||||
|
||||
if (b < 0x80) {
|
||||
/* end successfully because of last byte's msb(most significant bit) is zero */
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ENC_VARINT_QUIC:
|
||||
{
|
||||
/* calculate variable length */
|
||||
|
|
|
@ -1145,7 +1145,7 @@ extern tvbuff_t* base64uri_tvb_to_new_tvb(tvbuff_t* parent, int offset, int leng
|
|||
* @param offset The offset in tvb from which we begin trying to extract integer.
|
||||
* @param maxlen The maximum distance from offset that we may try to extract integer
|
||||
* @param value if parsing succeeds, parsed varint will store here.
|
||||
* @param encoding The ENC_* that defines the format (e.g., ENC_VARINT_PROTOBUF, ENC_VARINT_QUIC, ENC_VARINT_ZIGZAG)
|
||||
* @param encoding The ENC_* that defines the format (e.g., ENC_VARINT_PROTOBUF, ENC_VARINT_QUIC, ENC_VARINT_ZIGZAG, ENC_VARINT_SDNV)
|
||||
* @return the length of this varint in tvb. 0 means parsing failed.
|
||||
*/
|
||||
WS_DLL_PUBLIC guint tvb_get_varint(tvbuff_t *tvb, guint offset, guint maxlen, guint64 *value, const guint encoding);
|
||||
|
|
Loading…
Reference in New Issue