diff options
author | guy <guy@f5534014-38df-0310-8fa8-9805f1628bb7> | 2003-11-18 07:08:43 +0000 |
---|---|---|
committer | guy <guy@f5534014-38df-0310-8fa8-9805f1628bb7> | 2003-11-18 07:08:43 +0000 |
commit | 8fb0f694884b3194299b72c5e0b2ef15faf7cc3d (patch) | |
tree | 03817739425e14900038370d38c112944c6f5882 | |
parent | 6f6d80188fadad4f3f35ef457f05be8dcba3b75d (diff) |
Handle concatenated SPDUs.
Handle the Serial Number parameter.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@8998 f5534014-38df-0310-8fa8-9805f1628bb7
-rw-r--r-- | packet-ses.c | 222 |
1 files changed, 142 insertions, 80 deletions
diff --git a/packet-ses.c b/packet-ses.c index ede2591d59..deede77ff8 100644 --- a/packet-ses.c +++ b/packet-ses.c @@ -2,7 +2,7 @@ * * Routine to dissect ISO 8327-1 OSI Session Protocol packets * -* $Id: packet-ses.c,v 1.2 2003/11/11 20:33:53 guy Exp $ +* $Id: packet-ses.c,v 1.3 2003/11/18 07:08:43 guy Exp $ * * Yuriy Sidelnikov <YSidelnikov@hotmail.com> * @@ -308,16 +308,21 @@ get_item_len(tvbuff_t *tvb, int offset, int *len_len) return len; } -static void +static gboolean dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *param_tree, packet_info *pinfo, guint8 param_type, guint16 param_len) { + gboolean has_user_information = TRUE; + guint16 flags; + proto_item *tf; + proto_tree *flags_tree; + switch (param_type) { case Called_SS_user_Reference: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -328,7 +333,7 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, case Calling_SS_user_Reference: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -339,7 +344,7 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, case Common_Reference: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -350,7 +355,7 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, case Additional_Reference_Information: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -365,14 +370,10 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); - return; + break; } if (tree) { - guint8 flags; - proto_item *tf; - proto_tree *flags_tree; - flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_token_item_options_flags, tvb, offset, 1, @@ -396,7 +397,7 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); - return; + break; } if (tree) { @@ -446,14 +447,10 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); - return; + break; } if (tree) { - guint8 flags; - proto_item *tf; - proto_tree *flags_tree; - flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_connect_protocol_options_flags, tvb, offset, 1, @@ -472,14 +469,10 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 2", param_len); - return; + break; } if (tree) { - guint16 flags; - proto_item *tf; - proto_tree *flags_tree; - flags = tvb_get_ntohs(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_session_user_req_flags, tvb, offset, 2, @@ -532,7 +525,7 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 4", param_len); - return; + break; } if (tree) { @@ -551,14 +544,10 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); - return; + break; } if (tree) { - guint8 flags; - proto_item *tf; - proto_tree *flags_tree; - flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_version_number_options_flags, tvb, offset, 1, @@ -574,7 +563,7 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, case Initial_Serial_Number: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -589,15 +578,11 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); - return; + break; } + flags = tvb_get_guint8(tvb, offset); if (tree) { - guint8 flags; - proto_item *tf; - proto_tree *flags_tree; - - flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_enclosure_item_options_flags, tvb, offset, 1, flags); @@ -608,6 +593,17 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_boolean(flags_tree, hf_beginning_of_SSDU, tvb, offset, 1, flags); } + if (flags & END_SPDU) { + /* + * In Data Transfer and Typed Data SPDUs, + * "The User Information Field shall be present + * if the Enclosure Item is not present, or has + * bit 2 = 0", which presumably means it shall + * *not* be present if the Enclosure item *is* + * present and has bit 2 = 1. + */ + has_user_information = FALSE; + } break; case Token_Setting_Item: @@ -616,7 +612,7 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); - return; + break; } if (tree) { @@ -635,6 +631,17 @@ dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, } break; + case Serial_Number: + if (param_len == 0) + break; + if (tree) + { + proto_tree_add_item(param_tree, + hf_serial_number, + tvb, offset, param_len, FALSE); + } + break; + case Reason_Code: /* 0: Rejection by called SS-user; reason not specified. @@ -655,7 +662,7 @@ PICS. */ proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be >= 1", param_len); - return; + break; } if (tree) { @@ -677,7 +684,7 @@ PICS. */ case Calling_Session_Selector: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -688,7 +695,7 @@ PICS. */ case Called_Session_Selector: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -699,7 +706,7 @@ PICS. */ case Second_Serial_Number: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -710,7 +717,7 @@ PICS. */ case Second_Initial_Serial_Number: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -721,7 +728,7 @@ PICS. */ case Large_Initial_Serial_Number: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -732,7 +739,7 @@ PICS. */ case Large_Second_Initial_Serial_Number: if (param_len == 0) - return; + break; if (tree) { proto_tree_add_item(param_tree, @@ -744,12 +751,14 @@ PICS. */ default: break; } + return has_user_information; } -static void +static gboolean dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pg_tree, packet_info *pinfo, guint16 pg_len) { + gboolean has_user_information = TRUE; proto_item *ti; proto_tree *param_tree; guint8 param_type; @@ -775,7 +784,7 @@ dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree, proto_item_set_len(ti, pg_len + 1); proto_tree_add_text(param_tree, tvb, offset, pg_len, "Parameter length doesn't fit in parameter"); - return; + return has_user_information; } pg_len -= len_len; if (param_len > pg_len) { @@ -783,7 +792,7 @@ dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, pg_len, "Parameter length: %u, should be <= %u", param_len, pg_len); - return; + return has_user_information; } proto_item_set_len(ti, 1 + len_len + param_len); proto_tree_add_text(param_tree, tvb, offset, len_len, @@ -806,20 +815,27 @@ dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree, break; default: - dissect_parameter(tvb, offset, tree, - param_tree, pinfo, param_type, param_len); + if (!dissect_parameter(tvb, offset, tree, + param_tree, pinfo, param_type, param_len)) + has_user_information = FALSE; break; } } offset += param_len; pg_len -= param_len; } + return has_user_information; } -static void +/* + * Returns TRUE if there's a User Information field in this SPDU, FALSE + * otherwise. + */ +static gboolean dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree, proto_tree *ses_tree, packet_info *pinfo) { + gboolean has_user_information = TRUE; proto_item *ti; proto_tree *param_tree; guint8 param_type; @@ -845,7 +861,7 @@ dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree, proto_item_set_len(ti, len + 1 ); proto_tree_add_text(param_tree, tvb, offset, len, "Parameter length doesn't fit in parameter"); - return; + return has_user_information; } len -= len_len; if (param_len > len) { @@ -853,7 +869,7 @@ dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree, proto_tree_add_text(param_tree, tvb, offset, len, "Parameter length: %u, should be <= %u", param_len, len); - return; + return has_user_information; } proto_item_set_len(ti, 1 + len_len + param_len); proto_tree_add_text(param_tree, tvb, offset, len_len, @@ -877,30 +893,32 @@ dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree, case Connection_Identifier: case Linking_Information: /* Yes. */ - dissect_parameter_group(tvb, offset, tree, - param_tree, pinfo, param_len); + if (!dissect_parameter_group(tvb, offset, tree, + param_tree, pinfo, param_len)) + has_user_information = FALSE; break; /* everything else is a PI */ default: - dissect_parameter(tvb, offset, tree, - param_tree, pinfo, param_type, param_len); + if (!dissect_parameter(tvb, offset, tree, + param_tree, pinfo, param_type, param_len)) + has_user_information = FALSE; break; } } offset += param_len; len -= param_len; } + return has_user_information; } /* -* Dissect ses-encapsulated data in a SES stream. -*/ - -static void -dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) + * Dissect an SPDU. + */ +static int +dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { - int offset = 0; + gboolean has_user_information; guint8 type; proto_item *ti = NULL; proto_tree *ses_tree = NULL; @@ -908,12 +926,9 @@ dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) guint16 parameters_len; tvbuff_t *next_tvb; - if (check_col(pinfo->cinfo, COL_PROTOCOL)) - col_set_str(pinfo->cinfo, COL_PROTOCOL, "SES"); - if (check_col(pinfo->cinfo, COL_INFO)) - col_clear(pinfo->cinfo, COL_INFO); - -/* get SPDU type */ + /* + * Get SPDU type. + */ type = tvb_get_guint8(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, @@ -928,6 +943,22 @@ dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } offset++; + /* + * Might this SPDU have a User Information field? + */ + switch (type) { + + case SES_DATA_TRANSFER: + case SES_EXPEDITED: + case SES_TYPED_DATA: + has_user_information = TRUE; + break; + + default: + has_user_information = FALSE; + break; + } + /* get length of SPDU parameter field */ parameters_len = get_item_len(tvb, offset, &len_len); if (tree) @@ -936,24 +967,55 @@ dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset += len_len; /* Dissect parameters. */ - dissect_parameters(tvb, offset, parameters_len, tree, ses_tree, pinfo); + if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree, + pinfo)) + has_user_information = FALSE; offset += parameters_len; - /* Dissect user information */ - if (tvb_reported_length_remaining(tvb, offset) > 0) { - proto_item_set_end(ti, tvb, offset); - next_tvb = tvb_new_subset(tvb, offset, -1, -1); + proto_item_set_end(ti, tvb, offset); - /* do we have OSI presentation packet dissector ? */ - if(!pres_handle) - { - call_dissector(data_handle, next_tvb, pinfo, tree); - } - else - { - call_dissector(pres_handle, next_tvb, pinfo, tree); + /* Dissect user information, if present */ + if (has_user_information) { + if (tvb_reported_length_remaining(tvb, offset) > 0) { + next_tvb = tvb_new_subset(tvb, offset, -1, -1); + + /* do we have OSI presentation packet dissector ? */ + if(!pres_handle) + { + call_dissector(data_handle, next_tvb, pinfo, + tree); + } + else + { + call_dissector(pres_handle, next_tvb, pinfo, + tree); + } + + /* + * No more SPDUs to dissect. Set the offset to the + * end of the tvbuff. + */ + offset = tvb_length(tvb); } } + return offset; +} + +/* + * Dissect SPDUs inside a TSDU. + */ +static void +dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + int offset = 0; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SES"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + while (tvb_reported_length_remaining(tvb, offset) > 0) + offset = dissect_spdu(tvb, offset, pinfo, tree); } void |