/* packet-ses.c * * Routine to dissect ITU-T Rec. X.225 (1995 E)/ISO 8327-1 OSI Session Protocol packets * * Yuriy Sidelnikov * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include #include #include #include #include "packet-ber.h" #include "packet-ses.h" void proto_register_ses(void); void proto_reg_handoff_ses(void); void proto_register_clses(void); void proto_reg_handoff_clses(void); /* ses header fields */ static int proto_ses = -1; static int hf_ses_type = -1; static int hf_ses_type_0 = -1; static int hf_ses_length = -1; /* static int hf_ses_version = -1; */ /* static int hf_ses_reserved = -1; */ static int hf_ses_segment_data = -1; static int hf_ses_segments = -1; static int hf_ses_segment = -1; static int hf_ses_segment_overlap = -1; static int hf_ses_segment_overlap_conflicts = -1; static int hf_ses_segment_multiple_tails = -1; static int hf_ses_segment_too_long_segment = -1; static int hf_ses_segment_error = -1; static int hf_ses_segment_count = -1; static int hf_ses_reassembled_in = -1; static int hf_ses_reassembled_length = -1; /* ses fields defining a sub tree */ static gint ett_ses = -1; static gint ett_ses_param = -1; static gint ett_ses_segment = -1; static gint ett_ses_segments = -1; /* flags */ static int hf_connect_protocol_options_flags = -1; static int hf_version_number_options_flags = -1; static int hf_enclosure_item_options_flags = -1; static int hf_token_item_options_flags = -1; static gint ett_connect_protocol_options_flags = -1; static gint ett_transport_options_flags = -1; static gint ett_protocol_version_flags = -1; static gint ett_enclosure_item_flags = -1; static gint ett_token_item_flags = -1; static gint ett_ses_req_options_flags = -1; /* called SS user reference */ static int hf_called_ss_user_reference = -1; /* calling SS user reference */ static int hf_calling_ss_user_reference = -1; /* common reference */ static int hf_common_reference = -1; /* additional reference information */ static int hf_additional_reference_information = -1; /* token item */ static int hf_release_token = -1; static int hf_major_activity_token = -1; static int hf_synchronize_minor_token = -1; static int hf_data_token = -1; /* protocol options */ static int hf_able_to_receive_extended_concatenated_SPDU = -1; /* session requirement */ static int hf_session_user_req_flags = -1; static int hf_session_exception_report= -1; static int hf_data_separation_function_unit= -1; static int hf_symmetric_synchronize_function_unit= -1; static int hf_typed_data_function_unit= -1; static int hf_exception_function_unit= -1; static int hf_capability_function_unit=-1; static int hf_negotiated_release_function_unit= -1; static int hf_activity_management_function_unit= -1; static int hf_resynchronize_function_unit= -1; static int hf_major_resynchronize_function_unit= -1; static int hf_minor_resynchronize_function_unit= -1; static int hf_expedited_data_resynchronize_function_unit= -1; static int hf_duplex_function_unit= -1; static int hf_half_duplex_function_unit = -1; /* TSDU maximum size */ static int hf_proposed_tsdu_maximum_size_i2r = -1; static int hf_proposed_tsdu_maximum_size_r2i = -1; /* protocol version */ static int hf_protocol_version_1 = -1; static int hf_protocol_version_2 = -1; /* initial serial number */ static int hf_initial_serial_number = -1; /* enclosure item */ static int hf_beginning_of_SSDU = -1; static int hf_end_of_SSDU = -1; /* token setting item */ static const value_string token_setting_vals[] = { { 0x00, "initiator's side" }, { 0x01, "responder's side" }, { 0x02, "called SS user's choice" }, { 0x03, "reserved" }, { 0, NULL } }; static const true_false_string tfs_released_kept = { "Released", "Kept" }; static int hf_release_token_setting = -1; static int hf_major_activity_token_setting = -1; static int hf_synchronize_minor_token_setting = -1; static int hf_data_token_setting = -1; /* calling session selector */ static int hf_calling_session_selector = -1; /* called session selector */ static int hf_called_session_selector = -1; /* activity id */ static int hf_activity_identifier = -1; /* serial number */ static int hf_serial_number = -1; /* second serial number */ static int hf_second_serial_number = -1; /* second initial serial number */ static int hf_second_initial_serial_number = -1; /* large initial serial number */ static int hf_large_initial_serial_number = -1; /* large second initial serial number */ static int hf_large_second_initial_serial_number = -1; /* Generated from convert_proto_tree_add_text.pl */ static int hf_ses_reason_code = -1; static int hf_ses_transport_implementation_restriction = -1; static int hf_ses_transport_no_reason = -1; static int hf_ses_parameter_group_inside_parameter_group = -1; static int hf_ses_user_data = -1; static int hf_ses_parameter_type = -1; static int hf_ses_transport_protocol_error = -1; static int hf_ses_transport_user_abort = -1; static int hf_ses_parameter_length = -1; static int hf_ses_transport_connection = -1; static int hf_ses_transport_option_flags = -1; /* clses header fields */ static int proto_clses = -1; static expert_field ei_ses_bad_length = EI_INIT; static expert_field ei_ses_bad_parameter_length = EI_INIT; #define PROTO_STRING_CLSES "ISO 9548-1 OSI Connectionless Session Protocol" static dissector_handle_t pres_handle = NULL; static reassembly_table ses_reassembly_table; static const fragment_items ses_frag_items = { /* Segment subtrees */ &ett_ses_segment, &ett_ses_segments, /* Segment fields */ &hf_ses_segments, &hf_ses_segment, &hf_ses_segment_overlap, &hf_ses_segment_overlap_conflicts, &hf_ses_segment_multiple_tails, &hf_ses_segment_too_long_segment, &hf_ses_segment_error, &hf_ses_segment_count, /* Reassembled in field */ &hf_ses_reassembled_in, /* Reassembled length field */ &hf_ses_reassembled_length, /* Reassembled data field */ NULL, /* Tag */ "SES segments" }; static const value_string ses_vals[] = { {SES_DATA_TRANSFER, "DATA TRANSFER (DT) SPDU" }, /* 1 */ {SES_PLEASE_TOKENS, "PLEASE TOKENS (PT) SPDU" }, /* 2 */ {SES_EXPEDITED, "EXPEDITED (EX) SPDU" }, /* 5 */ {SES_PREPARE, "PREPARE (PR) SPDU" }, /* 7 */ {SES_NOT_FINISHED, "NOT FINISHED (NF) SPDU" }, /* 8 */ {SES_FINISH, "FINISH (FN) SPDU" }, /* 9 */ {SES_DISCONNECT, "DISCONNECT (DN) SPDU" }, /* 10 */ {SES_REFUSE, "REFUSE (RF) SPDU" }, /* 12 */ {SES_CONNECTION_REQUEST, "CONNECT (CN) SPDU" }, /* 13 */ {SES_CONNECTION_ACCEPT, "ACCEPT (AC) SPDU" }, /* 14 */ {SES_CONNECTION_DATA_OVERFLOW, "CONNECT DATA OVERFLOW (CDO) SPDU"}, /* 15 */ {SES_OVERFLOW_ACCEPT, "OVERFLOW ACCEPT (OA) SPDU" }, /* 16 */ {SES_GIVE_TOKENS_CONFIRM, "GIVE TOKENS CONFIRM (GTC) SPDU"}, /* 21 */ {SES_GIVE_TOKENS_ACK, "GIVE TOKENS ACK (GTA) SPDU" }, /* 22 */ {SES_ABORT, "ABORT (AB) SPDU" }, /* 25 */ {SES_ABORT_ACCEPT, "ABORT ACCEPT (AA) SPDU" }, /* 26 */ {SES_ACTIVITY_RESUME, "ACTIVITY RESUME (AR) SPDU" }, /* 29 */ {SES_TYPED_DATA, "TYPED DATA (TD) SPDU" }, /* 33 */ {SES_RESYNCHRONIZE_ACK, "RESYNCHRONIZE ACK (RA) SPDU" }, /* 34 */ {SES_MAJOR_SYNC_POINT, "MAJOR SYNC POINT (MAP) SPDU" }, /* 41 */ {SES_MAJOR_SYNC_ACK, "MAJOR SYNC ACK (MAA) SPDU" }, /* 42 */ {SES_ACTIVITY_START, "ACTIVITY START (AS) SPDU" }, /* 45 */ {SES_EXCEPTION_DATA, "EXCEPTION DATA (ED) SPDU" }, /* 48 */ {SES_MINOR_SYNC_POINT, "MINOR SYNC POINT (MIP) SPDU" }, /* 49 */ {SES_MINOR_SYNC_ACK, "MINOR SYNC ACK (MIA) SPDU" }, /* 50 */ {SES_RESYNCHRONIZE, "RESYNCHRONIZE (RS) SPDU" }, /* 53 */ {SES_ACTIVITY_DISCARD, "ACTIVITY DISCARD (AD) SPDU" }, /* 57 */ {SES_ACTIVITY_DISCARD_ACK, "ACTIVITY DISCARD ACK (ADA) SPDU" }, /* 58 */ {SES_CAPABILITY, "CAPABILITY DATA (CD) SPDU" }, /* 61 */ {SES_CAPABILITY_DATA_ACK, "CAPABILITY DATA ACK (CDA) SPDU" }, /* 62 */ {CLSES_UNIT_DATA, "UNIT DATA (UD) SPDU" }, /* 64 */ {SES_EXCEPTION_REPORT, "EXCEPTION REPORT (ER) SPDU" }, /* 0x2000 */ {0, NULL } }; value_string_ext ses_vals_ext = VALUE_STRING_EXT_INIT(ses_vals); static const value_string ses_category0_vals[] = { {SES_PLEASE_TOKENS, "Please tokens PDU" }, {SES_GIVE_TOKENS, "Give tokens PDU" }, {0, NULL } }; static const value_string param_vals[] = { {Connection_Identifier, "Connection Identifier"}, /* 1 */ {Connect_Accept_Item, "Connect Accept Item"}, /* 5 */ {Called_SS_user_Reference, "Called SS user Reference"}, /* 9 */ {Calling_SS_user_Reference, "Calling SS user Reference"}, /* 10 */ {Common_Reference, "Common Reference"}, /* 11 */ {Additional_Reference_Information, "Additional Reference Information"}, /* 12 */ {Sync_Type_Item, "Sync Type Item"}, /* 15 */ {Token_Item, "Token Item"}, /* 16 */ {Transport_Disconnect, "Transport_Disconnect"}, /* 17 */ {Protocol_Options, "Protocol Options"}, /* 19 */ {Session_Requirement, "Session Requirement"}, /* 20 */ {TSDU_Maximum_Size, "TSDU Maximum Size"}, /* 21 */ {Version_Number, "Version Number"}, /* 22 */ {Initial_Serial_Number, "Initial Serial Number"}, /* 23 */ {Prepare_Type, "Prepare Type"}, /* 24 */ {EnclosureItem, "Enclosure Item"}, /* 25 */ {Token_Setting_Item, "Token Setting Item"}, /* 26 */ {Resync_Type, "Resync Type"}, /* 27 */ {Linking_Information, "Linking Information"}, /* 33 */ {Activity_Identifier, "Activity Identifier"}, /* 41 */ {Serial_Number, "Serial Number"}, /* 42 */ {Reflect_Parameter, "Reflect Parameter"}, /* 49 */ {Reason_Code, "Reason Code"}, /* 50 */ {Calling_Session_Selector, "Calling Session Selector"}, /* 51 */ {Called_Session_Selector, "Called Session Selector"}, /* 52 */ {Second_Resync_Type, "Second Resync Type"}, /* 53 */ {Second_Serial_Number, "Second Serial Number"}, /* 54 */ {Second_Initial_Serial_Number, "Second Initial Serial Number"}, /* 55 */ {Upper_Limit_Serial_Number, "Upper Limit Serial Number"}, /* 56 */ {Large_Initial_Serial_Number, "Large Initial Serial Number"}, /* 57 */ {Large_Second_Initial_Serial_Number, "Large Second Initial Serial Number"}, /* 58 */ {Data_Overflow, "Data Overflow"}, /* 60 */ {User_Data, "Session user data"}, /* 193 */ {Extended_User_Data, "Session extended user data"}, /* 194 */ {0, NULL} }; static value_string_ext param_vals_ext = VALUE_STRING_EXT_INIT(param_vals); static const value_string reason_vals[] = { {reason_not_specified, "Rejection by called SS-user; reason not specified" }, {temporary_congestion, "Rejection by called SS-user due to temporary congestion" }, {Subsequent, "Rejection by called SS-user." }, {SES_DISCONNECT, "Rejection by the SPM; implementation restriction stated in the PICS" }, {Session_Selector_unknown, "Session Selector unknown" }, {SS_user_not_attached_to_SSAP, "SS-user not attached to SSAP" }, {SPM_congestion_at_connect_time, "SPM congestion at connect time" }, {versions_not_supported, "Proposed protocol versions not supported" }, {SPM_reason_not_specified, "Rejection by the SPM; reason not specified" }, {SPM_implementation_restriction, "Finish PDU" }, {0, NULL } }; static value_string_ext reason_vals_ext = VALUE_STRING_EXT_INIT(reason_vals); /* desegmentation of OSI over ses */ static gboolean ses_desegment = TRUE; /* RTSE reassembly data */ static guint ses_pres_ctx_id = 0; static gboolean ses_rtse_reassemble = FALSE; static void call_pres_dissector(tvbuff_t *tvb, int offset, guint16 param_len, packet_info *pinfo, proto_tree *tree, proto_tree *param_tree, struct SESSION_DATA_STRUCTURE *session) { /* do we have OSI presentation packet dissector ? */ if(!pres_handle) { /* No - display as data */ if (tree) { proto_tree_add_item(param_tree, hf_ses_user_data, tvb, offset, param_len, ENC_NA); } } else { /* Yes - call presentation dissector */ tvbuff_t *next_tvb; next_tvb = tvb_new_subset_length(tvb, offset, param_len); /* Pass the session pdu to the presentation dissector */ call_dissector_with_data(pres_handle, next_tvb, pinfo, tree, session); } } /* this routine returns length of parameter field, parameter group, or parameter */ static int get_item_len(tvbuff_t *tvb, int offset, int *len_len) { guint16 len; len = tvb_get_guint8(tvb, offset); if(len == TWO_BYTE_LEN) { len = tvb_get_ntohs(tvb, offset+1); *len_len = 3; } else *len_len = 1; return len; } 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, proto_item *param_len_item, guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session) { gboolean has_user_information = TRUE; guint16 flags; asn1_ctx_t asn1_ctx; static int * const item_option_flags[] = { &hf_release_token, &hf_major_activity_token, &hf_synchronize_minor_token, &hf_data_token, NULL }; static int * const transport_option_flags[] = { &hf_ses_transport_connection, &hf_ses_transport_user_abort, &hf_ses_transport_protocol_error, &hf_ses_transport_no_reason, &hf_ses_transport_implementation_restriction, NULL }; static int * const protocol_options_flags[] = { &hf_able_to_receive_extended_concatenated_SPDU, NULL }; static int * const req_options_flags[] = { &hf_session_exception_report, &hf_data_separation_function_unit, &hf_symmetric_synchronize_function_unit, &hf_typed_data_function_unit, &hf_exception_function_unit, &hf_capability_function_unit, &hf_negotiated_release_function_unit, &hf_activity_management_function_unit, &hf_resynchronize_function_unit, &hf_major_resynchronize_function_unit, &hf_minor_resynchronize_function_unit, &hf_expedited_data_resynchronize_function_unit, &hf_duplex_function_unit, &hf_half_duplex_function_unit, NULL }; static int * const version_flags[] = { &hf_protocol_version_2, &hf_protocol_version_1, NULL }; static int * const enclosure_flags[] = { &hf_end_of_SSDU, &hf_beginning_of_SSDU, NULL }; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); switch (param_type) { case Called_SS_user_Reference: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_called_ss_user_reference, tvb, offset, param_len, ENC_NA); break; case Calling_SS_user_Reference: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_calling_ss_user_reference, tvb, offset, param_len, ENC_NA); break; case Common_Reference: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_common_reference, tvb, offset, param_len, ENC_NA); break; case Additional_Reference_Information: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_additional_reference_information, tvb, offset, param_len, ENC_NA); break; case Token_Item: if (param_len != 1) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be 1", param_len); break; } proto_tree_add_bitmask(param_tree, tvb, offset, hf_token_item_options_flags, ett_token_item_flags, item_option_flags, ENC_NA); break; case Transport_Disconnect: if (param_len != 1) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be 1", param_len); break; } proto_tree_add_bitmask(param_tree, tvb, offset, hf_ses_transport_option_flags, ett_transport_options_flags, transport_option_flags, ENC_NA); if(tvb_get_guint8(tvb, offset) & user_abort ) { session->abort_type = SESSION_USER_ABORT; } else { session->abort_type = SESSION_PROVIDER_ABORT; } break; case Protocol_Options: if (param_len != 1) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be 1", param_len); break; } proto_tree_add_bitmask(param_tree, tvb, offset, hf_connect_protocol_options_flags, ett_connect_protocol_options_flags, protocol_options_flags, ENC_NA); break; case Session_Requirement: if (param_len != 2) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be 2", param_len); break; } proto_tree_add_bitmask(param_tree, tvb, offset, hf_session_user_req_flags, ett_ses_req_options_flags, req_options_flags, ENC_BIG_ENDIAN); break; case TSDU_Maximum_Size: if (param_len != 4) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be 4", param_len); break; } if (tree) { proto_tree_add_item(param_tree, hf_proposed_tsdu_maximum_size_i2r, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(param_tree, hf_proposed_tsdu_maximum_size_r2i, tvb, offset+2, 2, ENC_BIG_ENDIAN); } break; case Version_Number: if (param_len != 1) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be 1", param_len); break; } proto_tree_add_bitmask(param_tree, tvb, offset, hf_version_number_options_flags, ett_protocol_version_flags, version_flags, ENC_BIG_ENDIAN); break; case Initial_Serial_Number: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_initial_serial_number, tvb, offset, param_len, ENC_ASCII); break; case EnclosureItem: if (param_len != 1) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be 1", param_len); break; } flags = tvb_get_guint8(tvb, offset); *enclosure_item_flags = (guint8) flags; proto_tree_add_bitmask(param_tree, tvb, offset, hf_enclosure_item_options_flags, ett_enclosure_item_flags, enclosure_flags, ENC_BIG_ENDIAN); if (flags & END_SPDU) { /* * In Data Transfer and Typed Data SPDUs, (X.225: 8.3.{11,13}.4) * "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. */ if(!(flags & BEGINNING_SPDU)) { /* X.225 7.11.2 also states: * "All DATA TRANSFER SPDUs, except the last DATA TRANSFER SPDU in a sequence greater than one, must have user information" * So if BEGINNING_SPDU and END_SPDU are set in the enclosure item, then this is presumably a sequence of one and * consequently there must be user information. * * So, there is only no user information if *only* END_SPDU is set. */ has_user_information = FALSE; } } break; case Token_Setting_Item: if (param_len != 1) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be 1", param_len); break; } if (tree) { proto_tree_add_item(param_tree, hf_release_token_setting, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(param_tree, hf_major_activity_token_setting, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(param_tree, hf_synchronize_minor_token_setting, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(param_tree, hf_data_token_setting, tvb, offset, 1, ENC_BIG_ENDIAN); } break; case Activity_Identifier: if (param_len == 0) break; /* 8.3.29.2 The parameter fields shall be as specified in Table 37. * Activity Identifier m 41 6 octets maximum */ proto_tree_add_item(param_tree, hf_activity_identifier, tvb, offset, param_len, ENC_NA); break; case Serial_Number: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_serial_number, tvb, offset, param_len, ENC_ASCII); break; case Reason_Code: /* 0: Rejection by called SS-user; reason not specified. 1: Rejection by called SS-user due to temporary congestion. 2: Rejection by called SS-user. Subsequent octets may be used for user data up to a length of 512 octets if Protocol Version 1 has been selected, and up to a length such that the total length (including SI and LI) of the SPDU does not exceed 65 539 octets if Protocol Version 2 has been selected. 128 + 1: Session Selector unknown. 128 + 2: SS-user not attached to SSAP. 128 + 3: SPM congestion at connect time. 128 + 4: Proposed protocol versions not supported. 128 + 5: Rejection by the SPM; reason not specified. 128 + 6: Rejection by the SPM; implementation restriction stated in the PICS. */ if (param_len < 1) { expert_add_info_format(pinfo, param_len_item, &ei_ses_bad_length, "Length is %u, should be >= 1", param_len); break; } proto_tree_add_item(param_tree, hf_ses_reason_code, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; param_len--; if (param_len != 0) { call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); } break; case Calling_Session_Selector: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_calling_session_selector, tvb, offset, param_len, ENC_NA); break; case Called_Session_Selector: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_called_session_selector, tvb, offset, param_len, ENC_NA); break; case Second_Serial_Number: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_second_serial_number, tvb, offset, param_len, ENC_ASCII); break; case Second_Initial_Serial_Number: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_second_initial_serial_number, tvb, offset, param_len, ENC_ASCII); break; case Large_Initial_Serial_Number: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_large_initial_serial_number, tvb, offset, param_len, ENC_ASCII); break; case Large_Second_Initial_Serial_Number: if (param_len == 0) break; proto_tree_add_item(param_tree, hf_large_second_initial_serial_number, tvb, offset, param_len, ENC_ASCII); break; default: break; } return has_user_information; } static gboolean dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *pg_tree, packet_info *pinfo, guint16 pg_len, guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session) { gboolean has_user_information = TRUE; proto_item *ti, *param_len_item; proto_tree *param_tree; guint8 param_type; const char *param_str; int len_len; guint16 param_len; while(pg_len != 0) { param_type = tvb_get_guint8(tvb, offset); param_tree = proto_tree_add_subtree(pg_tree, tvb, offset, -1, ett_ses_param, &ti, val_to_str_ext(param_type, ¶m_vals_ext, "Unknown parameter type (0x%02x)")); param_str = val_to_str_ext_const(param_type, ¶m_vals_ext, "Unknown"); proto_tree_add_item(param_tree, hf_ses_parameter_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; pg_len--; param_len = get_item_len(tvb, offset, &len_len); if (len_len > pg_len) { proto_item_set_len(ti, pg_len + 1); proto_tree_add_expert_format(param_tree, pinfo, &ei_ses_bad_parameter_length, tvb, offset, pg_len, "Parameter length doesn't fit in parameter"); return has_user_information; } pg_len -= len_len; if (param_len > pg_len) { proto_item_set_len(ti, pg_len + 1 + len_len); proto_tree_add_expert_format(param_tree, pinfo, &ei_ses_bad_parameter_length, tvb, offset, pg_len, "Parameter length: %u, should be <= %u", param_len, pg_len); return has_user_information; } proto_item_set_len(ti, 1 + len_len + param_len); param_len_item = proto_tree_add_uint(param_tree, hf_ses_parameter_length, tvb, offset, len_len, param_len); offset += len_len; if (param_str != NULL) { switch(param_type) { /* PG's in PG's are invalid, presumably */ case Extended_User_Data: case User_Data: case Connect_Accept_Item: case Connection_Identifier: case Linking_Information: proto_tree_add_item(param_tree, hf_ses_parameter_group_inside_parameter_group, tvb, offset, param_len, ENC_NA); break; default: if (!dissect_parameter(tvb, offset, tree, param_tree, pinfo, param_type, param_len, param_len_item, enclosure_item_flags, session)) has_user_information = FALSE; break; } } offset += param_len; pg_len -= param_len; } return has_user_information; } /* * 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, guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session) { gboolean has_user_information = TRUE; proto_item *ti, *param_len_item; proto_tree *param_tree; guint8 param_type; const char *param_str; int len_len; guint16 param_len; while (len != 0) { param_type = tvb_get_guint8(tvb, offset); param_tree = proto_tree_add_subtree(ses_tree, tvb, offset, -1, ett_ses_param, &ti, val_to_str_ext(param_type, ¶m_vals_ext, "Unknown parameter type (0x%02x)")); param_str = val_to_str_ext_const(param_type, ¶m_vals_ext, "Unknown"); proto_tree_add_item(param_tree, hf_ses_parameter_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; len--; param_len = get_item_len(tvb, offset, &len_len); if (len_len > len) { proto_item_set_len(ti, len + 1 ); proto_tree_add_expert_format(param_tree, pinfo, &ei_ses_bad_parameter_length, tvb, offset, len, "Parameter length doesn't fit in parameter"); return has_user_information; } len -= len_len; if (param_len > len) { proto_item_set_len(ti, len + 1 + len_len); proto_tree_add_expert_format(param_tree, pinfo, &ei_ses_bad_parameter_length, tvb, offset, len, "Parameter length: %u, should be <= %u", param_len, len); return has_user_information; } proto_item_set_len(ti, 1 + len_len + param_len); param_len_item = proto_tree_add_uint(param_tree, hf_ses_parameter_length, tvb, offset, len_len, param_len); offset += len_len; if (param_str != NULL) { switch(param_type) { case Extended_User_Data: call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); break; case User_Data: call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); break; /* handle PGI's */ case Connect_Accept_Item: case Connection_Identifier: case Linking_Information: /* Yes. */ if (!dissect_parameter_group(tvb, offset, tree, param_tree, pinfo, param_len, enclosure_item_flags, session)) has_user_information = FALSE; break; /* everything else is a PI */ default: if (!dissect_parameter(tvb, offset, tree, param_tree, pinfo, param_type, param_len, param_len_item, enclosure_item_flags, session)) has_user_information = FALSE; break; } } offset += param_len; len -= param_len; } return has_user_information; } /* * Dissect an SPDU. */ static int dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, gboolean tokens, gboolean connectionless) { gboolean has_user_information = FALSE; guint8 type; proto_item *ti = NULL; proto_tree *ses_tree = NULL; int len_len; guint16 parameters_len; tvbuff_t *next_tvb = NULL; guint32 *pres_ctx_id = NULL; guint8 enclosure_item_flags = BEGINNING_SPDU|END_SPDU; struct SESSION_DATA_STRUCTURE session; /* * Get SPDU type. */ type = tvb_get_guint8(tvb, offset); session.spdu_type = type; session.abort_type = SESSION_NO_ABORT; session.pres_ctx_id = 0; session.ros_op = 0; session.rtse_reassemble = FALSE; if(connectionless) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str_ext(type, &ses_vals_ext, "Unknown SPDU type (0x%02x)")); if (tree) { ti = proto_tree_add_item(tree, proto_clses, tvb, offset, -1, ENC_NA); ses_tree = proto_item_add_subtree(ti, ett_ses); proto_tree_add_uint(ses_tree, hf_ses_type, tvb, offset, 1, type); } has_user_information = TRUE; } else if (tokens) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)")); if (tree) { ti = proto_tree_add_item(tree, proto_ses, tvb, offset, -1, ENC_NA); ses_tree = proto_item_add_subtree(ti, ett_ses); proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb, offset, 1, type); } } else { col_add_str(pinfo->cinfo, COL_INFO, val_to_str_ext(type, &ses_vals_ext, "Unknown SPDU type (0x%02x)")); if (tree) { ti = proto_tree_add_item(tree, proto_ses, tvb, offset, -1, ENC_NA); ses_tree = proto_item_add_subtree(ti, ett_ses); proto_tree_add_uint(ses_tree, hf_ses_type, tvb, offset, 1, type); } /* * 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; case SES_MAJOR_SYNC_POINT: pres_ctx_id = (guint32 *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ses, 0); if (ses_rtse_reassemble != 0 && !pres_ctx_id) { /* First time visited - save pres_ctx_id */ pres_ctx_id = wmem_new(wmem_file_scope(), guint32); *pres_ctx_id = ses_pres_ctx_id; p_add_proto_data(wmem_file_scope(), pinfo, proto_ses, 0, pres_ctx_id); } if (pres_ctx_id) { session.pres_ctx_id = *pres_ctx_id; session.rtse_reassemble = TRUE; has_user_information = TRUE; } ses_rtse_reassemble = FALSE; break; } } offset++; /* get length of SPDU parameter field */ parameters_len = get_item_len(tvb, offset, &len_len); if (tree) proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset, len_len, parameters_len); offset += len_len; /* Dissect parameters. */ if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree, pinfo, &enclosure_item_flags, &session)) has_user_information = FALSE; offset += parameters_len; proto_item_set_end(ti, tvb, offset); /* Dissect user information, if present */ if (!ses_desegment || enclosure_item_flags == (BEGINNING_SPDU|END_SPDU)) { if (has_user_information) { /* Not desegment or only one segment */ if (tvb_reported_length_remaining(tvb, offset) > 0 || type == SES_MAJOR_SYNC_POINT) { next_tvb = tvb_new_subset_remaining(tvb, offset); } } } else { conversation_t *conversation = NULL; fragment_head *frag_msg = NULL; gint fragment_len; guint32 ses_id = 0; /* Use conversation index as segment id */ conversation = find_conversation_pinfo(pinfo, 0); if (conversation != NULL) { ses_id = conversation->conv_index; } fragment_len = tvb_reported_length_remaining (tvb, offset); ti = proto_tree_add_item (ses_tree, hf_ses_segment_data, tvb, offset, fragment_len, ENC_NA); proto_item_append_text (ti, " (%d byte%s)", fragment_len, plurality (fragment_len, "", "s")); frag_msg = fragment_add_seq_next (&ses_reassembly_table, tvb, offset, pinfo, ses_id, NULL, fragment_len, (enclosure_item_flags & END_SPDU) ? FALSE : TRUE); next_tvb = process_reassembled_data (tvb, offset, pinfo, "Reassembled SES", frag_msg, &ses_frag_items, NULL, (enclosure_item_flags & END_SPDU) ? tree : ses_tree); has_user_information = TRUE; offset += fragment_len; } if (has_user_information && next_tvb) { if (!pres_handle) { call_data_dissector(next_tvb, pinfo, tree); } else { /* Pass the session pdu to the presentation dissector */ call_dissector_with_data(pres_handle, next_tvb, pinfo, tree, &session); } /* * No more SPDUs to dissect. Set the offset to the * end of the tvbuff. */ offset = tvb_captured_length(tvb); if (session.rtse_reassemble && type == SES_DATA_TRANSFER) { ses_pres_ctx_id = session.pres_ctx_id; ses_rtse_reassemble = TRUE; } } return offset; } /* * Dissect SPDUs inside a TSDU. */ static int dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { int offset = 0; guint8 type; gboolean is_clsp = FALSE; type = tvb_get_guint8(tvb, offset); if(type == CLSES_UNIT_DATA) is_clsp = TRUE; col_set_str(pinfo->cinfo, COL_PROTOCOL, is_clsp ? "CLSES" : "SES"); col_clear(pinfo->cinfo, COL_INFO); /* * Do we have a category 0 SPDU (GIVE_TOKENS/PLEASE_TOKENS) as * the first SPDU? * * If so, dissect it as such (GIVE_TOKENS and DATA_TRANSFER have * the same SPDU type value). */ if ((type == SES_PLEASE_TOKENS) || (type == SES_GIVE_TOKENS)) offset = dissect_spdu(tvb, offset, pinfo, tree, TOKENS_SPDU, FALSE); /* Dissect the remaining SPDUs. */ while (tvb_reported_length_remaining(tvb, offset) > 0) offset = dissect_spdu(tvb, offset, pinfo, tree, NON_TOKENS_SPDU, is_clsp); return tvb_captured_length(tvb); } static gboolean dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_) { /* must check that this really is a ses packet */ int offset = 0; guint8 type; int len_len; guint16 len; /* first, check do we have at least 4 bytes (type+length) */ if (tvb_captured_length(tvb) < 2) return FALSE; /* no */ /* can we recognize session PDU ? Return FALSE if not */ /* get SPDU type */ type = tvb_get_guint8(tvb, offset); /* check SPDU type */ if (try_val_to_str_ext(type, &ses_vals_ext) == NULL) { return FALSE; /* no, it isn't a session PDU */ } /* can we recognize the second session PDU if the first one was * a Give Tokens PDU? Return FALSE if not */ if(tvb_bytes_exist(tvb, 2, 2) && type == SES_GIVE_TOKENS) { /* get SPDU type */ type = tvb_get_guint8(tvb, offset+2); /* check SPDU type */ if (try_val_to_str_ext(type, &ses_vals_ext) == NULL) { return FALSE; /* no, it isn't a session PDU */ } } /* some Siemens SIMATIC protocols also use COTP, and shouldn't be * misinterpreted as SES. * the starter in this case is fixed to 0x32 (SES_MINOR_SYNC_ACK for SES), * so if the parameter type is unknown, it's probably SIMATIC */ if(type == 0x32 && tvb_captured_length(tvb) >= 3) { type = tvb_get_guint8(tvb, offset+2); if (try_val_to_str_ext(type, ¶m_vals_ext) == NULL) { return FALSE; /* it's probably a SIMATIC protocol */ } } /* OK,let's check SPDU length */ /* get length of SPDU */ len = get_item_len(tvb, offset+1, &len_len); /* add header length */ len+=len_len; /* do we have enough bytes ? */ if (tvb_reported_length(tvb) < len) return FALSE; /* no */ /* final check to see if the next SPDU, if present, is also valid */ if (tvb_captured_length(tvb) > 1+(guint) len) { type = tvb_get_guint8(tvb, offset + len + 1); /* check SPDU type */ if (try_val_to_str_ext(type, &ses_vals_ext) == NULL) { return FALSE; /* no, it isn't a session PDU */ } } dissect_ses(tvb, pinfo, parent_tree, data); return TRUE; } void proto_register_ses(void) { static hf_register_info hf[] = { { &hf_ses_type, { "SPDU Type", "ses.type", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ses_vals_ext, 0x0, NULL, HFILL } }, { &hf_ses_type_0, { "SPDU Type", "ses.type", FT_UINT8, BASE_DEC, VALS(ses_category0_vals), 0x0, NULL, HFILL } }, { &hf_ses_length, { "Length", "ses.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, #if 0 { &hf_ses_version, { "Version", "ses.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, #endif #if 0 { &hf_ses_reserved, { "Reserved", "ses.reserved", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, #endif { &hf_called_ss_user_reference, { "Called SS User Reference", "ses.called_ss_user_reference", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_calling_ss_user_reference, { "Calling SS User Reference", "ses.calling_ss_user_reference", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_common_reference, { "Common Reference", "ses.common_reference", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_additional_reference_information, { "Additional Reference Information", "ses.additional_reference_information", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_release_token, { "release token", "ses.release_token", FT_BOOLEAN, 8, NULL, RELEASE_TOKEN, NULL, HFILL } }, { &hf_major_activity_token, { "major/activity token", "ses.major.token", FT_BOOLEAN, 8, NULL, MAJOR_ACTIVITY_TOKEN, NULL, HFILL } }, { &hf_synchronize_minor_token, { "synchronize minor token", "ses.synchronize_token", FT_BOOLEAN, 8, NULL, SYNCHRONIZE_MINOR_TOKEN, NULL, HFILL } }, { &hf_data_token, { "data token", "ses.data_token", FT_BOOLEAN, 8, NULL, DATA_TOKEN, "data token", HFILL } }, { &hf_able_to_receive_extended_concatenated_SPDU, { "Able to receive extended concatenated SPDU", "ses.connect.f1", FT_BOOLEAN, 8, NULL, SES_EXT_CONT, NULL, HFILL } }, { &hf_session_user_req_flags, { "Flags", "ses.req.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_session_exception_report, { "Session exception report", "ses.exception_report", FT_BOOLEAN, 16, NULL, SES_EXCEPTION_REPORT, NULL, HFILL } }, { &hf_data_separation_function_unit, { "Data separation function unit", "ses.data_sep", FT_BOOLEAN, 16, NULL, DATA_SEPARATION_FUNCTION_UNIT, NULL, HFILL } }, { &hf_symmetric_synchronize_function_unit, { "Symmetric synchronize function unit", "ses.symm_sync", FT_BOOLEAN, 16, NULL, SYMMETRIC_SYNCHRONIZE_FUNCTION_UNIT, NULL, HFILL } }, { &hf_typed_data_function_unit, { "Typed data function unit", "ses.typed_data", FT_BOOLEAN, 16, NULL, TYPED_DATA_FUNCTION_UNIT, NULL, HFILL } }, { &hf_exception_function_unit, { "Exception function unit", "ses.exception_data", FT_BOOLEAN, 16, NULL, EXCEPTION_FUNCTION_UNIT, NULL, HFILL } }, { &hf_capability_function_unit, { "Capability function unit", "ses.capability_data", FT_BOOLEAN, 16, NULL, CAPABILITY_DATA_FUNCTION_UNIT, NULL, HFILL } }, { &hf_negotiated_release_function_unit, { "Negotiated release function unit", "ses.negotiated_release", FT_BOOLEAN, 16, NULL, NEGOTIATED_RELEASE_FUNCTION_UNIT, NULL, HFILL } }, { &hf_activity_management_function_unit, { "Activity management function unit", "ses.activity_management", FT_BOOLEAN, 16, NULL, ACTIVITY_MANAGEMENT_FUNCTION_UNIT, NULL, HFILL } }, { &hf_resynchronize_function_unit, { "Resynchronize function unit", "ses.resynchronize", FT_BOOLEAN, 16, NULL, RESYNCHRONIZE_FUNCTION_UNIT, NULL, HFILL } }, { &hf_major_resynchronize_function_unit, { "Major resynchronize function unit", "ses.major_resynchronize", FT_BOOLEAN, 16, NULL, MAJOR_SYNCHRONIZE_FUNCTION_UNIT, NULL, HFILL } }, { &hf_minor_resynchronize_function_unit, { "Minor resynchronize function unit", "ses.minor_resynchronize", FT_BOOLEAN, 16, NULL, MINOR_SYNCHRONIZE_FUNCTION_UNIT, NULL, HFILL } }, { &hf_expedited_data_resynchronize_function_unit, { "Expedited data function unit", "ses.expedited_data", FT_BOOLEAN, 16, NULL, EXPEDITED_DATA_FUNCTION_UNIT, NULL, HFILL } }, { &hf_duplex_function_unit, { "Duplex functional unit", "ses.duplex", FT_BOOLEAN, 16, NULL, DUPLEX_FUNCTION_UNIT, NULL, HFILL } }, { &hf_half_duplex_function_unit, { "Half-duplex functional unit", "ses.half_duplex", FT_BOOLEAN, 16, NULL, HALF_DUPLEX_FUNCTION_UNIT, NULL, HFILL } }, { &hf_proposed_tsdu_maximum_size_i2r, { "Proposed TSDU Maximum Size, Initiator to Responder", "ses.proposed_tsdu_maximum_size_i2r", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_proposed_tsdu_maximum_size_r2i, { "Proposed TSDU Maximum Size, Responder to Initiator", "ses.proposed_tsdu_maximum_size_r2i", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_protocol_version_1, { "Protocol Version 1", "ses.protocol_version1", FT_BOOLEAN, 8, NULL, PROTOCOL_VERSION_1, NULL, HFILL } }, { &hf_protocol_version_2, { "Protocol Version 2", "ses.protocol_version2", FT_BOOLEAN, 8, NULL, PROTOCOL_VERSION_2, NULL, HFILL } }, { &hf_initial_serial_number, { "Initial Serial Number", "ses.initial_serial_number", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_beginning_of_SSDU, { "beginning of SSDU", "ses.beginning_of_SSDU", FT_BOOLEAN, 8, NULL, BEGINNING_SPDU, NULL, HFILL } }, { &hf_end_of_SSDU, { "end of SSDU", "ses.end_of_SSDU", FT_BOOLEAN, 8, NULL, END_SPDU, NULL, HFILL } }, { &hf_release_token_setting, { "release token setting", "ses.release_token_setting", FT_UINT8, BASE_HEX, VALS(token_setting_vals), 0xC0, NULL, HFILL } }, { &hf_major_activity_token_setting, { "major/activity setting", "ses.major_activity_token_setting", FT_UINT8, BASE_HEX, VALS(token_setting_vals), 0x30, "major/activity token setting", HFILL } }, { &hf_synchronize_minor_token_setting, { "synchronize-minor token setting", "ses.synchronize_minor_token_setting", FT_UINT8, BASE_HEX, VALS(token_setting_vals), 0x0C, NULL, HFILL } }, { &hf_data_token_setting, { "data token setting", "ses.data_token_setting", FT_UINT8, BASE_HEX, VALS(token_setting_vals), 0x03, NULL, HFILL } }, { &hf_activity_identifier, { "Activity Identifier", "ses.activity_identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_serial_number, { "Serial Number", "ses.serial_number", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_calling_session_selector, { "Calling Session Selector", "ses.calling_session_selector", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_called_session_selector, { "Called Session Selector", "ses.called_session_selector", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_second_serial_number, { "Second Serial Number", "ses.second_serial_number", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_second_initial_serial_number, { "Second Initial Serial Number", "ses.second_initial_serial_number", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_large_initial_serial_number, { "Large Initial Serial Number", "ses.large_initial_serial_number", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_large_second_initial_serial_number, { "Large Second Initial Serial Number", "ses.large_second_initial_serial_number", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_connect_protocol_options_flags, { "Flags", "ses.connect.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_version_number_options_flags, { "Flags", "ses.version.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_token_item_options_flags, { "Flags", "ses.tken_item.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_enclosure_item_options_flags, { "Flags", "ses.enclosure.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_ses_segment_data, { "SES segment data", "ses.segment.data", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } }, { &hf_ses_segments, { "SES segments", "ses.segments", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } }, { &hf_ses_segment, { "SES segment", "ses.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, { &hf_ses_segment_overlap, { "SES segment overlap", "ses.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_ses_segment_overlap_conflicts, { "SES segment overlapping with conflicting data", "ses.segment.overlap.conflicts", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_ses_segment_multiple_tails, { "SES has multiple tail segments", "ses.segment.multiple_tails", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_ses_segment_too_long_segment, { "SES segment too long", "ses.segment.too_long_segment", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_ses_segment_error, { "SES desegmentation error", "ses.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, { &hf_ses_segment_count, { "SES segment count", "ses.segment.count", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }, { &hf_ses_reassembled_in, { "Reassembled SES in frame", "ses.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL, 0x00, "This SES packet is reassembled in this frame", HFILL } }, { &hf_ses_reassembled_length, { "Reassembled SES length", "ses.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x00, "The total length of the reassembled payload", HFILL } }, /* Generated from convert_proto_tree_add_text.pl */ { &hf_ses_user_data, { "User data", "ses.user_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_ses_transport_option_flags, { "Flags", "ses.transport_flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_ses_transport_connection, { "Transport connection", "ses.transport_flags.connection", FT_BOOLEAN, 8, TFS(&tfs_released_kept), transport_connection_is_released, NULL, HFILL }}, { &hf_ses_transport_user_abort, { "User abort", "ses.transport_flags.user_abort", FT_BOOLEAN, 8, TFS(&tfs_yes_no), user_abort, NULL, HFILL }}, { &hf_ses_transport_protocol_error, { "Protocol error", "ses.transport_flags.protocol_error", FT_BOOLEAN, 8, TFS(&tfs_yes_no), protocol_error, NULL, HFILL }}, { &hf_ses_transport_no_reason, { "No reason", "ses.transport_flags.no_reason", FT_BOOLEAN, 8, TFS(&tfs_yes_no), no_reason, NULL, HFILL }}, { &hf_ses_transport_implementation_restriction, { "Implementation restriction", "ses.transport_flags.implementation_restriction", FT_BOOLEAN, 8, TFS(&tfs_yes_no), implementation_restriction, NULL, HFILL }}, { &hf_ses_reason_code, { "Reason Code", "ses.reason_code", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &reason_vals_ext, 0x0, NULL, HFILL }}, { &hf_ses_parameter_type, { "Parameter type", "ses.parameter_type", FT_UINT8, BASE_DEC|BASE_EXT_STRING, ¶m_vals_ext, 0x0, NULL, HFILL }}, { &hf_ses_parameter_length, { "Parameter length", "ses.parameter_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_ses_parameter_group_inside_parameter_group, { "Parameter group inside parameter group", "ses.parameter_group_inside_parameter_group", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, }; static gint *ett[] = { &ett_ses, &ett_ses_param, &ett_connect_protocol_options_flags, &ett_transport_options_flags, &ett_protocol_version_flags, &ett_enclosure_item_flags, &ett_token_item_flags, &ett_ses_req_options_flags, &ett_ses_segment, &ett_ses_segments }; static ei_register_info ei[] = { { &ei_ses_bad_length, { "ses.bad_length", PI_MALFORMED, PI_ERROR, "Bad length", EXPFILL }}, { &ei_ses_bad_parameter_length, { "ses.bad_parameter_length", PI_MALFORMED, PI_ERROR, "Bad parameter length", EXPFILL }}, }; module_t *ses_module; expert_module_t* expert_ses; proto_ses = proto_register_protocol(PROTO_STRING_SES, "SES", "ses"); proto_register_field_array(proto_ses, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); expert_ses = expert_register_protocol(proto_ses); expert_register_field_array(expert_ses, ei, array_length(ei)); reassembly_table_register (&ses_reassembly_table, &addresses_reassembly_table_functions); ses_module = prefs_register_protocol(proto_ses, NULL); prefs_register_bool_preference(ses_module, "desegment", "Reassemble session packets ", "Whether the session dissector should reassemble messages spanning multiple SES segments", &ses_desegment); /* * Register the dissector by name, so other dissectors can * grab it by name rather than just referring to it directly * (you can't refer to it directly from a plugin dissector * on Windows without stuffing it into the Big Transfer Vector). */ register_dissector("ses", dissect_ses, proto_ses); } void proto_reg_handoff_ses(void) { /* define sub dissector */ pres_handle = find_dissector_add_dependency("pres", proto_ses); /* add our session dissector to cotp dissector list * and cotp_is dissector list*/ heur_dissector_add("cotp", dissect_ses_heur, "SES over COTP", "ses_cotp", proto_ses, HEURISTIC_ENABLE); heur_dissector_add("cotp_is", dissect_ses_heur, "SES over COTP (inactive subset)", "ses_cotp_is", proto_ses, HEURISTIC_ENABLE); } void proto_register_clses(void) { proto_clses = proto_register_protocol(PROTO_STRING_CLSES, "CLSP", "clsp"); } void proto_reg_handoff_clses(void) { /* add our session dissector to cltp dissector list */ heur_dissector_add("cltp", dissect_ses_heur, "CLSP over COTP", "clses_cotp", proto_clses, HEURISTIC_ENABLE); } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 8 * tab-width: 8 * indent-tabs-mode: t * End: * * vi: set shiftwidth=8 tabstop=8 noexpandtab: * :indentSize=8:tabSize=8:noTabs=false: */