aboutsummaryrefslogtreecommitdiffstats
path: root/packet-ses.c
diff options
context:
space:
mode:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2003-11-18 07:08:43 +0000
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2003-11-18 07:08:43 +0000
commit8fb0f694884b3194299b72c5e0b2ef15faf7cc3d (patch)
tree03817739425e14900038370d38c112944c6f5882 /packet-ses.c
parent6f6d80188fadad4f3f35ef457f05be8dcba3b75d (diff)
Handle concatenated SPDUs.
Handle the Serial Number parameter. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@8998 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'packet-ses.c')
-rw-r--r--packet-ses.c222
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