3 * Routine to dissect ITU-T Rec. X.225 (1995 E)/ISO 8327-1 OSI Session Protocol packets
7 * Yuriy Sidelnikov <YSidelnikov@hotmail.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include <epan/packet.h>
38 #include <epan/asn1.h>
39 #include "packet-ber.h"
40 #include "packet-ses.h"
41 #include "packet-frame.h"
43 /* #include <epan/prefs.h> */
44 #include <epan/emem.h>
45 #include <epan/strutil.h>
47 /* ses header fields */
48 static int proto_ses = -1;
49 static int hf_ses_type = -1;
50 static int hf_ses_type_0 = -1;
51 static int hf_ses_length = -1;
52 static int hf_ses_version = -1;
53 static int hf_ses_reserved = -1;
55 /* ses fields defining a sub tree */
56 static gint ett_ses = -1;
57 static gint ett_ses_param = -1;
60 ----------------------------------------------------------------------------------------------------------*/
61 static dissector_handle_t pres_handle = NULL;
63 ----------------------------------------------------------------------------------------------------------*/
67 static int hf_connect_protocol_options_flags = -1;
68 static int hf_version_number_options_flags = -1;
69 static int hf_enclosure_item_options_flags = -1;
70 static int hf_token_item_options_flags = -1;
72 static gint ett_connect_protocol_options_flags = -1;
73 static gint ett_protocol_version_flags = -1;
74 static gint ett_enclosure_item_flags = -1;
75 static gint ett_token_item_flags = -1;
76 static gint ett_ses_req_options_flags = -1;
78 /* called SS user reference */
79 static int hf_called_ss_user_reference = -1;
81 /* calling SS user reference */
82 static int hf_calling_ss_user_reference = -1;
84 /* common reference */
85 static int hf_common_reference = -1;
87 /* additional reference information */
88 static int hf_additional_reference_information = -1;
91 static int hf_release_token = -1;
92 static int hf_major_activity_token = -1;
93 static int hf_synchronize_minor_token = -1;
94 static int hf_data_token = -1;
96 /* protocol options */
97 static int hf_able_to_receive_extended_concatenated_SPDU = -1;
99 /* session requirement */
100 static int hf_session_user_req_flags = -1;
101 static int hf_session_exception_report= -1;
102 static int hf_data_separation_function_unit= -1;
103 static int hf_symmetric_synchronize_function_unit= -1;
104 static int hf_typed_data_function_unit= -1;
105 static int hf_exception_function_unit= -1;
106 static int hf_capability_function_unit=-1;
107 static int hf_negotiated_release_function_unit= -1;
108 static int hf_activity_management_function_unit= -1;
109 static int hf_resynchronize_function_unit= -1;
110 static int hf_major_resynchronize_function_unit= -1;
111 static int hf_minor_resynchronize_function_unit= -1;
112 static int hf_expedited_data_resynchronize_function_unit= -1;
113 static int hf_duplex_function_unit= -1;
114 static int hf_half_duplex_function_unit = -1;
116 /* TSDU maximum size */
117 static int hf_proposed_tsdu_maximum_size_i2r = -1;
118 static int hf_proposed_tsdu_maximum_size_r2i = -1;
120 /* protocol version */
121 static int hf_protocol_version_1 = -1;
122 static int hf_protocol_version_2 = -1;
124 /* initial serial number */
125 static int hf_initial_serial_number = -1;
128 static int hf_beginning_of_SSDU = -1;
129 static int hf_end_of_SSDU = -1;
131 /* token setting item */
133 static const value_string token_setting_vals[] = {
134 { 0x00, "initiator's side" },
135 { 0x01, "responder's side" },
136 { 0x02, "called SS user's choice" },
137 { 0x03, "reserved" },
141 static int hf_release_token_setting = -1;
142 static int hf_major_activity_token_setting = -1;
143 static int hf_synchronize_minor_token_setting = -1;
144 static int hf_data_token_setting = -1;
146 /* calling session selector */
147 static int hf_calling_session_selector = -1;
149 /* called session selector */
150 static int hf_called_session_selector = -1;
153 static int hf_activity_identifier = -1;
156 static int hf_serial_number = -1;
158 /* second serial number */
159 static int hf_second_serial_number = -1;
161 /* second initial serial number */
162 static int hf_second_initial_serial_number = -1;
164 /* large initial serial number */
165 static int hf_large_initial_serial_number = -1;
167 /* large second initial serial number */
168 static int hf_large_second_initial_serial_number = -1;
170 const value_string ses_vals[] =
172 {SES_CONNECTION_REQUEST, "CONNECT (CN) SPDU" }, /* 13 */
173 {SES_CONNECTION_ACCEPT, "ACCEPT (AC) SPDU" }, /* 14 */
174 {SES_EXCEPTION_REPORT, "EXCEPTION REPORT (ER) SPDU" }, /* 0 */
175 {SES_DATA_TRANSFER, "DATA TRANSFER (DT) SPDU" }, /* 1 */
176 {SES_PLEASE_TOKENS, "PLEASE TOKENS (PT) SPDU" }, /* 2 */
177 {SES_EXPEDITED, "EXPEDITED (EX) SPDU" }, /* 5 */
178 {SES_PREPARE, "PREPARE (PR) SPDU" }, /* 7 */
179 {SES_NOT_FINISHED, "NOT FINISHED (NF) SPDU" }, /* 8 */
180 {SES_FINISH, "FINISH (FN) SPDU" }, /* 9 */
181 {SES_DISCONNECT, "DISCONNECT (DN) SPDU" }, /* 10 */
182 {SES_REFUSE, "REFUSE (RF) SPDU" }, /* 12 */
183 {SES_CONNECTION_DATA_OVERFLOW, "CONNECT DATA OVERFLOW (CDO) SPDU"},/* 15 */
184 {SES_OVERFLOW_ACCEPT, "OVERFLOW ACCEPT (OA) SPDU" }, /* 16 */
185 {SES_GIVE_TOKENS_CONFIRM, "GIVE TOKENS CONFIRM (GTC) SPDU"}, /* 21 */
186 {SES_GIVE_TOKENS_ACK, "GIVE TOKENS ACK (GTA) SPDU" }, /* 22 */
187 {SES_ABORT, "ABORT (AB) SPDU" }, /* 25 */
188 {SES_ABORT_ACCEPT, "ABORT ACCEPT (AA) SPDU" }, /* 26 */
189 {SES_ACTIVITY_RESUME, "ACTIVITY RESUME (AR) SPDU" }, /* 29 */
190 {SES_TYPED_DATA, "TYPED DATA (TD) SPDU" }, /* 33 */
191 {SES_RESYNCHRONIZE_ACK, "RESYNCHRONIZE ACK (RA) SPDU" }, /* 34 */
192 {SES_MAJOR_SYNC_POINT, "MAJOR SYNC POINT (MAP) SPDU" }, /* 41 */
193 {SES_MAJOR_SYNC_ACK, "MAJOR SYNC ACK (MAA) SPDU" }, /* 42 */
194 {SES_ACTIVITY_START, "ACTIVITY START (AS) SPDU" }, /* 45 */
195 {SES_EXCEPTION_DATA, "EXCEPTION DATA (ED) SPDU" }, /* 48 */
196 {SES_MINOR_SYNC_POINT, "MINOR SYNC POINT (MIP) SPDU" }, /* 49 */
197 {SES_MINOR_SYNC_ACK, "MINOR SYNC ACK (MIA) SPDU" }, /* 50 */
198 {SES_RESYNCHRONIZE, "RESYNCHRONIZE (RS) SPDU" }, /* 53 */
199 {SES_ACTIVITY_DISCARD, "ACTIVITY DISCARD (AD) SPDU" }, /* 57 */
200 {SES_ACTIVITY_DISCARD_ACK, "ACTIVITY DISCARD ACK (ADA) SPDU" },/* 58 */
201 {SES_CAPABILITY, "CAPABILITY DATA (CD) SPDU" }, /* 61 */
202 {SES_CAPABILITY_DATA_ACK, "CAPABILITY DATA ACK (CDA) SPDU" }, /* 62 */
206 static const value_string ses_category0_vals[] =
208 {SES_PLEASE_TOKENS, "Please tokens PDU" },
209 {SES_GIVE_TOKENS, "Give tokens PDU" },
214 static const value_string param_vals[] =
216 {Connection_Identifier, "Connection Identifier"},
217 {Connect_Accept_Item, "Connect Accept Item"},
218 {Called_SS_user_Reference, "Called SS user Reference"},
219 {Calling_SS_user_Reference, "Calling SS user Reference"},
220 {Common_Reference, "Common Reference"},
221 {Sync_Type_Item, "Sync Type Item"},
222 {Token_Item, "Token Item"},
223 {Transport_Disconnect, "Transport_Disconnect"},
224 {Additional_Reference_Information, "Additional Reference Information"},
225 {Protocol_Options, "Protocol Options"},
226 {TSDU_Maximum_Size, "TSDU Maximum Size"},
227 {Version_Number, "Version Number"},
228 {Initial_Serial_Number, "Initial Serial Number"},
229 {Prepare_Type, "Prepare Type"},
230 {EnclosureItem, "Enclosure Item"},
231 {Token_Setting_Item, "Token Setting Item"},
232 {Resync_Type, "Resync Type"},
233 {Activity_Identifier, "Activity Identifier"},
234 {Serial_Number, "Serial Number"},
235 {Linking_Information, "Linking Information"},
236 {Reflect_Parameter, "Reflect Parameter"},
237 {Reason_Code, "Reason Code"},
238 {Calling_Session_Selector, "Calling Session Selector"},
239 {Called_Session_Selector, "Called Session Selector"},
240 {Second_Resync_Type, "Second Resync Type"},
241 {Second_Serial_Number, "Second Serial Number"},
242 {Second_Initial_Serial_Number, "Second Initial Serial Number"},
243 {Upper_Limit_Serial_Number, "Upper Limit Serial Number"},
244 {Large_Initial_Serial_Number, "Large Initial Serial Number"},
245 {Large_Second_Initial_Serial_Number, "Large Second Initial Serial Number"},
246 {Data_Overflow, "Data Overflow"},
247 {Session_Requirement, "Session Requirement"},
248 {User_Data, "Session user data"},
249 {Extended_User_Data, "Session extended user data"},
253 static const value_string reason_vals[] =
255 {reason_not_specified, "Rejection by called SS-user; reason not specified" },
256 {temporary_congestion, "Rejection by called SS-user due to temporary congestion" },
257 {Subsequent, "Rejection by called SS-user." },
258 {Session_Selector_unknown, "Session Selector unknown" },
259 {SS_user_not_attached_to_SSAP, "SS-user not attached to SSAP" },
260 {SPM_congestion_at_connect_time, "SPM congestion at connect time" },
261 {versions_not_supported, "Proposed protocol versions not supported" },
262 {SPM_reason_not_specified, "Rejection by the SPM; reason not specified" },
263 {SPM_implementation_restriction, "Finish PDU" },
264 {SES_DISCONNECT, "Rejection by the SPM; implementation restriction stated in the PICS" },
268 /* desegmentation of OSI over ses */
269 /*static gboolean ses_desegment = TRUE;*/
271 /* RTSE reassembly data */
272 static guint ses_pres_ctx_id = 0;
273 static gboolean ses_rtse_reassemble = FALSE;
275 /* find the dissector for data */
276 static dissector_handle_t data_handle;
279 call_pres_dissector(tvbuff_t *tvb, int offset, guint16 param_len,
280 packet_info *pinfo, proto_tree *tree, proto_tree *param_tree,
281 struct SESSION_DATA_STRUCTURE *session)
283 void *saved_private_data;
285 /* do we have OSI presentation packet dissector ? */
288 /* No - display as data */
291 proto_tree_add_text(param_tree, tvb, offset, param_len,
297 /* Yes - call presentation dissector */
300 next_tvb = tvb_new_subset(tvb, offset, param_len, param_len);
303 /* save type of session pdu. We'll need it in the presentation dissector */
304 saved_private_data = pinfo->private_data;
305 pinfo->private_data = session;
306 call_dissector(pres_handle, next_tvb, pinfo, tree);
307 pinfo->private_data = saved_private_data;
311 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
317 /* this routine returns length of parameter field, parameter group,
320 get_item_len(tvbuff_t *tvb, int offset, int *len_len)
324 len = tvb_get_guint8(tvb, offset);
325 if(len == TWO_BYTE_LEN)
327 len = tvb_get_ntohs(tvb, offset+1);
336 dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree,
337 proto_tree *param_tree, packet_info *pinfo, guint8 param_type,
338 guint16 param_len, struct SESSION_DATA_STRUCTURE *session)
340 gboolean has_user_information = TRUE;
343 proto_tree *flags_tree;
345 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
349 case Called_SS_user_Reference:
354 proto_tree_add_item(param_tree,
355 hf_called_ss_user_reference,
356 tvb, offset, param_len, FALSE);
360 case Calling_SS_user_Reference:
365 proto_tree_add_item(param_tree,
366 hf_calling_ss_user_reference,
367 tvb, offset, param_len, FALSE);
371 case Common_Reference:
376 proto_tree_add_item(param_tree,
378 tvb, offset, param_len, FALSE);
382 case Additional_Reference_Information:
387 proto_tree_add_item(param_tree,
388 hf_additional_reference_information,
389 tvb, offset, param_len, FALSE);
396 proto_tree_add_text(param_tree, tvb, offset,
397 param_len, "Length is %u, should be 1",
403 flags = tvb_get_guint8(tvb, offset);
404 tf = proto_tree_add_uint(param_tree,
405 hf_token_item_options_flags, tvb, offset, 1,
407 flags_tree = proto_item_add_subtree(tf,
408 ett_token_item_flags);
409 proto_tree_add_boolean(flags_tree, hf_release_token,
410 tvb, offset, 1, flags);
411 proto_tree_add_boolean(flags_tree,
412 hf_major_activity_token, tvb, offset, 1, flags);
413 proto_tree_add_boolean(flags_tree,
414 hf_synchronize_minor_token, tvb, offset, 1, flags);
415 proto_tree_add_boolean(flags_tree, hf_data_token, tvb,
420 case Transport_Disconnect:
423 proto_tree_add_text(param_tree, tvb, offset,
424 param_len, "Length is %u, should be 1",
432 flags = tvb_get_guint8(tvb, offset);
433 if(flags & transport_connection_is_released )
435 proto_tree_add_text(param_tree, tvb, offset, 1,
436 "transport connection is released");
440 proto_tree_add_text(param_tree, tvb, offset, 1,
441 "transport connection is kept");
444 if(flags & user_abort )
446 proto_tree_add_text(param_tree, tvb, offset, 1,
448 session->abort_type = SESSION_USER_ABORT;
452 session->abort_type = SESSION_PROVIDER_ABORT;
455 if(flags & protocol_error )
457 proto_tree_add_text(param_tree, tvb, offset, 1,
461 if(flags & no_reason )
463 proto_tree_add_text(param_tree, tvb, offset, 1,
467 if(flags & implementation_restriction )
469 proto_tree_add_text(param_tree, tvb, offset, 1,
470 "implementation restriction");
475 case Protocol_Options:
478 proto_tree_add_text(param_tree, tvb, offset,
479 param_len, "Length is %u, should be 1",
485 flags = tvb_get_guint8(tvb, offset);
486 tf = proto_tree_add_uint(param_tree,
487 hf_connect_protocol_options_flags, tvb, offset, 1,
489 flags_tree = proto_item_add_subtree(tf,
490 ett_connect_protocol_options_flags);
491 proto_tree_add_boolean(flags_tree,
492 hf_able_to_receive_extended_concatenated_SPDU,
493 tvb, offset, 1, flags);
497 case Session_Requirement:
500 proto_tree_add_text(param_tree, tvb, offset,
501 param_len, "Length is %u, should be 2",
507 flags = tvb_get_ntohs(tvb, offset);
508 tf = proto_tree_add_uint(param_tree,
509 hf_session_user_req_flags, tvb, offset, 2,
511 flags_tree = proto_item_add_subtree(tf,
512 ett_ses_req_options_flags);
513 proto_tree_add_boolean(flags_tree,
514 hf_session_exception_report, tvb, offset, 2, flags);
515 proto_tree_add_boolean(flags_tree,
516 hf_data_separation_function_unit, tvb, offset, 2,
518 proto_tree_add_boolean(flags_tree,
519 hf_symmetric_synchronize_function_unit,
520 tvb, offset, 2, flags);
521 proto_tree_add_boolean(flags_tree,
522 hf_typed_data_function_unit, tvb, offset, 2, flags);
523 proto_tree_add_boolean(flags_tree,
524 hf_exception_function_unit, tvb, offset, 2, flags);
525 proto_tree_add_boolean(flags_tree,
526 hf_capability_function_unit, tvb, offset, 2, flags);
527 proto_tree_add_boolean(flags_tree,
528 hf_negotiated_release_function_unit,
529 tvb, offset, 2, flags);
530 proto_tree_add_boolean(flags_tree,
531 hf_activity_management_function_unit,
532 tvb, offset, 2, flags);
533 proto_tree_add_boolean(flags_tree,
534 hf_resynchronize_function_unit, tvb, offset, 2,
536 proto_tree_add_boolean(flags_tree,
537 hf_major_resynchronize_function_unit,
538 tvb, offset, 2, flags);
539 proto_tree_add_boolean(flags_tree,
540 hf_minor_resynchronize_function_unit,
541 tvb, offset, 2, flags);
542 proto_tree_add_boolean(flags_tree,
543 hf_expedited_data_resynchronize_function_unit,
544 tvb, offset, 2, flags);
545 proto_tree_add_boolean(flags_tree,
546 hf_duplex_function_unit, tvb, offset, 2, flags);
547 proto_tree_add_boolean(flags_tree,
548 hf_half_duplex_function_unit,
549 tvb, offset, 2, flags);
553 case TSDU_Maximum_Size:
556 proto_tree_add_text(param_tree, tvb, offset,
557 param_len, "Length is %u, should be 4",
563 proto_tree_add_item(param_tree,
564 hf_proposed_tsdu_maximum_size_i2r,
565 tvb, offset, 2, FALSE);
566 proto_tree_add_item(param_tree,
567 hf_proposed_tsdu_maximum_size_r2i,
568 tvb, offset+2, 2, FALSE);
575 proto_tree_add_text(param_tree, tvb, offset,
576 param_len, "Length is %u, should be 1",
582 flags = tvb_get_guint8(tvb, offset);
583 tf = proto_tree_add_uint(param_tree,
584 hf_version_number_options_flags, tvb, offset, 1,
586 flags_tree = proto_item_add_subtree(tf,
587 ett_protocol_version_flags);
588 proto_tree_add_boolean(flags_tree,
589 hf_protocol_version_2, tvb, offset, 1, flags);
590 proto_tree_add_boolean(flags_tree,
591 hf_protocol_version_1, tvb, offset, 1, flags);
595 case Initial_Serial_Number:
600 proto_tree_add_item(param_tree,
601 hf_initial_serial_number,
602 tvb, offset, param_len, FALSE);
609 proto_tree_add_text(param_tree, tvb, offset,
610 param_len, "Length is %u, should be 1",
614 flags = tvb_get_guint8(tvb, offset);
617 tf = proto_tree_add_uint(param_tree,
618 hf_enclosure_item_options_flags, tvb, offset, 1,
620 flags_tree = proto_item_add_subtree(tf,
621 ett_enclosure_item_flags);
622 proto_tree_add_boolean(flags_tree, hf_end_of_SSDU,
623 tvb, offset, 1, flags);
624 proto_tree_add_boolean(flags_tree, hf_beginning_of_SSDU,
625 tvb, offset, 1, flags);
627 if (flags & END_SPDU) {
629 * In Data Transfer and Typed Data SPDUs, (X.225: 8.3.{11,13}.4)
630 * "The User Information Field shall be present
631 * if the Enclosure Item is not present, or has
632 * bit 2 = 0", which presumably means it shall
633 * *not* be present if the Enclosure item *is*
634 * present and has bit 2 = 1.
637 if(!(flags & BEGINNING_SPDU)) {
638 /* X.225 7.11.2 also states:
639 * "All DATA TRANSFER SPDUs, except the last DATA TRANSFER SPDU in a sequence greater than one, must have user information"
640 * So if BEGINNING_SPDU and END_SPDU are set in the enclosure item, then this is presumably a sequence of one and
641 * consequently there must be user information.
643 * So, there is only no user information if *only* END_SPDU is set.
646 has_user_information = FALSE;
651 case Token_Setting_Item:
654 proto_tree_add_text(param_tree, tvb, offset,
655 param_len, "Length is %u, should be 1",
661 proto_tree_add_item(param_tree,
662 hf_release_token_setting,
663 tvb, offset, 1, FALSE);
664 proto_tree_add_item(param_tree,
665 hf_major_activity_token_setting,
666 tvb, offset, 1, FALSE);
667 proto_tree_add_item(param_tree,
668 hf_synchronize_minor_token_setting,
669 tvb, offset, 1, FALSE);
670 proto_tree_add_item(param_tree,
671 hf_data_token_setting,
672 tvb, offset, 1, FALSE);
676 case Activity_Identifier:
681 dissect_ber_integer(FALSE, &asn1_ctx, param_tree, tvb, offset,
682 hf_activity_identifier, NULL);
691 proto_tree_add_item(param_tree,
693 tvb, offset, param_len, FALSE);
699 0: Rejection by called SS-user; reason not specified.
700 1: Rejection by called SS-user due to temporary congestion.
701 2: Rejection by called SS-user. Subsequent octets may be used for user data
702 up to a length of 512 octets if Protocol Version 1 has been selected, and up
703 to a length such that the total length (including SI and LI) of the SPDU
704 does not exceed 65 539 octets if Protocol Version 2 has been selected.
705 128 + 1: Session Selector unknown.
706 128 + 2: SS-user not attached to SSAP.
707 128 + 3: SPM congestion at connect time.
708 128 + 4: Proposed protocol versions not supported.
709 128 + 5: Rejection by the SPM; reason not specified.
710 128 + 6: Rejection by the SPM; implementation restriction stated in the
714 proto_tree_add_text(param_tree, tvb, offset,
715 param_len, "Length is %u, should be >= 1",
723 reason_code = tvb_get_guint8(tvb, offset);
724 proto_tree_add_text(param_tree, tvb, offset, 1,
726 val_to_str(reason_code, reason_vals, "Unknown (%u)"));
732 call_pres_dissector(tvb, offset, param_len,
733 pinfo, tree, param_tree, session);
737 case Calling_Session_Selector:
742 proto_tree_add_item(param_tree,
743 hf_calling_session_selector,
744 tvb, offset, param_len, FALSE);
748 case Called_Session_Selector:
753 proto_tree_add_item(param_tree,
754 hf_called_session_selector,
755 tvb, offset, param_len, FALSE);
759 case Second_Serial_Number:
764 proto_tree_add_item(param_tree,
765 hf_second_serial_number,
766 tvb, offset, param_len, FALSE);
770 case Second_Initial_Serial_Number:
775 proto_tree_add_item(param_tree,
776 hf_second_initial_serial_number,
777 tvb, offset, param_len, FALSE);
781 case Large_Initial_Serial_Number:
786 proto_tree_add_item(param_tree,
787 hf_large_initial_serial_number,
788 tvb, offset, param_len, FALSE);
792 case Large_Second_Initial_Serial_Number:
797 proto_tree_add_item(param_tree,
798 hf_large_second_initial_serial_number,
799 tvb, offset, param_len, FALSE);
806 return has_user_information;
810 dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree,
811 proto_tree *pg_tree, packet_info *pinfo, guint16 pg_len,
812 struct SESSION_DATA_STRUCTURE *session)
814 gboolean has_user_information = TRUE;
816 proto_tree *param_tree;
818 const char *param_str;
824 param_type = tvb_get_guint8(tvb, offset);
825 ti = proto_tree_add_text(pg_tree, tvb, offset, -1, "%s",
826 val_to_str(param_type, param_vals,
827 "Unknown parameter type (0x%02x)"));
828 param_tree = proto_item_add_subtree(ti, ett_ses_param);
829 param_str = match_strval(param_type, param_vals);
830 proto_tree_add_text(param_tree, tvb, offset, 1,
831 "Parameter type: %s",
832 param_str != NULL ? param_str : "Unknown");
835 param_len = get_item_len(tvb, offset, &len_len);
836 if (len_len > pg_len) {
837 proto_item_set_len(ti, pg_len + 1);
838 proto_tree_add_text(param_tree, tvb, offset, pg_len,
839 "Parameter length doesn't fit in parameter");
840 return has_user_information;
843 if (param_len > pg_len) {
844 proto_item_set_len(ti, pg_len + 1 + len_len);
845 proto_tree_add_text(param_tree, tvb, offset, pg_len,
846 "Parameter length: %u, should be <= %u",
848 return has_user_information;
850 proto_item_set_len(ti, 1 + len_len + param_len);
851 proto_tree_add_text(param_tree, tvb, offset, len_len,
852 "Parameter length: %u", param_len);
855 if (param_str != NULL)
859 /* PG's in PG's are invalid, presumably */
860 case Extended_User_Data:
862 case Connect_Accept_Item:
863 case Connection_Identifier:
864 case Linking_Information:
865 proto_tree_add_text(param_tree, tvb, offset,
867 "Parameter group inside parameter group");
871 if (!dissect_parameter(tvb, offset, tree,
872 param_tree, pinfo, param_type, param_len,
874 has_user_information = FALSE;
881 return has_user_information;
885 * Returns TRUE if there's a User Information field in this SPDU, FALSE
889 dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree,
890 proto_tree *ses_tree, packet_info *pinfo,
891 struct SESSION_DATA_STRUCTURE *session)
893 gboolean has_user_information = TRUE;
895 proto_tree *param_tree;
897 const char *param_str;
903 param_type = tvb_get_guint8(tvb, offset);
904 ti = proto_tree_add_text(ses_tree, tvb, offset, -1, "%s",
905 val_to_str(param_type, param_vals,
906 "Unknown parameter type (0x%02x)"));
907 param_tree = proto_item_add_subtree(ti, ett_ses_param);
908 param_str = match_strval(param_type, param_vals);
909 proto_tree_add_text(param_tree, tvb, offset, 1,
910 "Parameter type: %s",
911 param_str != NULL ? param_str : "Unknown");
914 param_len = get_item_len(tvb, offset, &len_len);
916 proto_item_set_len(ti, len + 1 );
917 proto_tree_add_text(param_tree, tvb, offset, len,
918 "Parameter length doesn't fit in parameter");
919 return has_user_information;
922 if (param_len > len) {
923 proto_item_set_len(ti, len + 1 + len_len);
924 proto_tree_add_text(param_tree, tvb, offset, len,
925 "Parameter length: %u, should be <= %u",
927 return has_user_information;
929 proto_item_set_len(ti, 1 + len_len + param_len);
930 proto_tree_add_text(param_tree, tvb, offset, len_len,
931 "Parameter length: %u", param_len);
934 if (param_str != NULL)
938 case Extended_User_Data:
939 call_pres_dissector(tvb, offset, param_len,
940 pinfo, tree, param_tree, session);
944 call_pres_dissector(tvb, offset, param_len,
945 pinfo, tree, param_tree, session);
949 case Connect_Accept_Item:
950 case Connection_Identifier:
951 case Linking_Information:
953 if (!dissect_parameter_group(tvb, offset, tree,
954 param_tree, pinfo, param_len, session))
955 has_user_information = FALSE;
958 /* everything else is a PI */
960 if (!dissect_parameter(tvb, offset, tree,
961 param_tree, pinfo, param_type, param_len,
963 has_user_information = FALSE;
970 return has_user_information;
977 dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
980 gboolean has_user_information = FALSE;
982 proto_item *ti = NULL;
983 proto_tree *ses_tree = NULL;
985 guint16 parameters_len;
987 void *save_private_data;
988 guint32 *pres_ctx_id = NULL;
989 struct SESSION_DATA_STRUCTURE session;
994 type = tvb_get_guint8(tvb, offset);
995 session.spdu_type = type;
996 session.abort_type = SESSION_NO_ABORT;
998 session.rtse_reassemble = FALSE;
1001 if (check_col(pinfo->cinfo, COL_INFO))
1002 col_add_str(pinfo->cinfo, COL_INFO,
1003 val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)"));
1005 ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
1007 ses_tree = proto_item_add_subtree(ti, ett_ses);
1008 proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb,
1012 if (check_col(pinfo->cinfo, COL_INFO))
1013 col_add_str(pinfo->cinfo, COL_INFO,
1014 val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
1016 ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
1018 ses_tree = proto_item_add_subtree(ti, ett_ses);
1019 proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
1024 * Might this SPDU have a User Information field?
1028 case SES_DATA_TRANSFER:
1030 case SES_TYPED_DATA:
1031 has_user_information = TRUE;
1033 case SES_MAJOR_SYNC_POINT:
1034 pres_ctx_id = p_get_proto_data (pinfo->fd, proto_ses);
1035 if (ses_rtse_reassemble != 0 && !pres_ctx_id) {
1036 /* First time visited - save pres_ctx_id */
1037 pres_ctx_id = se_alloc (sizeof (guint32));
1038 *pres_ctx_id = ses_pres_ctx_id;
1039 p_add_proto_data (pinfo->fd, proto_ses, pres_ctx_id);
1042 session.pres_ctx_id = *pres_ctx_id;
1043 session.rtse_reassemble = TRUE;
1044 has_user_information = TRUE;
1046 ses_rtse_reassemble = FALSE;
1052 /* get length of SPDU parameter field */
1053 parameters_len = get_item_len(tvb, offset, &len_len);
1055 proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset,
1056 len_len, parameters_len);
1059 /* Dissect parameters. */
1060 if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree,
1062 has_user_information = FALSE;
1063 offset += parameters_len;
1065 proto_item_set_end(ti, tvb, offset);
1067 /* Dissect user information, if present */
1068 if (has_user_information) {
1069 if (tvb_reported_length_remaining(tvb, offset) > 0 || type == SES_MAJOR_SYNC_POINT) {
1070 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1072 /* do we have OSI presentation packet dissector ? */
1075 call_dissector(data_handle, next_tvb, pinfo,
1080 /* save type of session pdu. We'll need it in the presentation dissector */
1081 save_private_data = pinfo->private_data;
1082 pinfo->private_data = &session;
1083 call_dissector(pres_handle, next_tvb, pinfo,
1085 pinfo->private_data = save_private_data;
1089 * No more SPDUs to dissect. Set the offset to the
1090 * end of the tvbuff.
1092 offset = tvb_length(tvb);
1093 if (session.rtse_reassemble && type == SES_DATA_TRANSFER) {
1094 ses_pres_ctx_id = session.pres_ctx_id;
1095 ses_rtse_reassemble = TRUE;
1103 * Dissect SPDUs inside a TSDU.
1106 dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1111 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SES");
1112 if (check_col(pinfo->cinfo, COL_INFO))
1113 col_clear(pinfo->cinfo, COL_INFO);
1116 * Do we have a category 0 SPDU (GIVE_TOKENS/PLEASE_TOKENS) as
1119 * If so, dissect it as such (GIVE_TOKENS and DATA_TRANSFER have
1120 * the same SPDU type value).
1122 type = tvb_get_guint8(tvb, offset);
1123 if (type == SES_PLEASE_TOKENS || type == SES_GIVE_TOKENS)
1124 offset = dissect_spdu(tvb, offset, pinfo, tree, TOKENS_SPDU);
1126 /* Dissect the remaining SPDUs. */
1127 while (tvb_reported_length_remaining(tvb, offset) > 0)
1128 offset = dissect_spdu(tvb, offset, pinfo, tree, NON_TOKENS_SPDU);
1132 proto_register_ses(void)
1134 static hf_register_info hf[] =
1155 VALS(ses_category0_vals),
1198 &hf_called_ss_user_reference,
1200 "Called SS User Reference",
1201 "ses.called_ss_user_reference",
1202 FT_BYTES, BASE_NONE,
1210 &hf_calling_ss_user_reference,
1212 "Calling SS User Reference",
1213 "ses.calling_ss_user_reference",
1214 FT_BYTES, BASE_NONE,
1222 &hf_common_reference,
1225 "ses.common_reference",
1226 FT_BYTES, BASE_NONE,
1234 &hf_additional_reference_information,
1236 "Additional Reference Information",
1237 "ses.additional_reference_information",
1238 FT_BYTES, BASE_NONE,
1249 "ses.release_token",
1258 &hf_major_activity_token,
1260 "major/activity token",
1264 MAJOR_ACTIVITY_TOKEN,
1270 &hf_synchronize_minor_token,
1272 "synchronize minor token",
1273 "ses.synchronize_token",
1276 SYNCHRONIZE_MINOR_TOKEN,
1294 &hf_able_to_receive_extended_concatenated_SPDU,
1296 "Able to receive extended concatenated SPDU",
1306 &hf_session_user_req_flags,
1319 &hf_session_exception_report,
1321 "Session exception report",
1322 "ses.exception_report.",
1325 SES_EXCEPTION_REPORT,
1331 &hf_data_separation_function_unit,
1333 "Data separation function unit",
1337 DATA_SEPARATION_FUNCTION_UNIT,
1343 &hf_symmetric_synchronize_function_unit,
1345 "Symmetric synchronize function unit",
1349 SYMMETRIC_SYNCHRONIZE_FUNCTION_UNIT,
1355 &hf_typed_data_function_unit,
1357 "Typed data function unit",
1361 TYPED_DATA_FUNCTION_UNIT,
1367 &hf_exception_function_unit,
1369 "Exception function unit",
1370 "ses.exception_data",
1373 EXCEPTION_FUNCTION_UNIT,
1379 &hf_capability_function_unit,
1381 "Capability function unit",
1382 "ses.capability_data",
1385 CAPABILITY_DATA_FUNCTION_UNIT,
1391 &hf_negotiated_release_function_unit,
1393 "Negotiated release function unit",
1394 "ses.negotiated_release",
1397 NEGOTIATED_RELEASE_FUNCTION_UNIT,
1403 &hf_activity_management_function_unit,
1405 "Activity management function unit",
1406 "ses.activity_management",
1409 ACTIVITY_MANAGEMENT_FUNCTION_UNIT,
1415 &hf_resynchronize_function_unit,
1417 "Resynchronize function unit",
1418 "ses.resynchronize",
1421 RESYNCHRONIZE_FUNCTION_UNIT,
1427 &hf_major_resynchronize_function_unit,
1429 "Major resynchronize function unit",
1430 "ses.major_resynchronize",
1433 MAJOR_SYNCHRONIZE_FUNCTION_UNIT,
1439 &hf_minor_resynchronize_function_unit,
1441 "Minor resynchronize function unit",
1442 "ses.minor_resynchronize",
1445 MINOR_SYNCHRONIZE_FUNCTION_UNIT,
1451 &hf_expedited_data_resynchronize_function_unit,
1453 "Expedited data function unit",
1454 "ses.expedited_data",
1457 EXPEDITED_DATA_FUNCTION_UNIT,
1463 &hf_duplex_function_unit,
1465 "Duplex functional unit",
1469 DUPLEX_FUNCTION_UNIT,
1475 &hf_half_duplex_function_unit,
1477 "Half-duplex functional unit",
1481 HALF_DUPLEX_FUNCTION_UNIT,
1487 &hf_proposed_tsdu_maximum_size_i2r,
1489 "Proposed TSDU Maximum Size, Initiator to Responder",
1490 "ses.proposed_tsdu_maximum_size_i2r",
1500 &hf_proposed_tsdu_maximum_size_r2i,
1502 "Proposed TSDU Maximum Size, Responder to Initiator",
1503 "ses.proposed_tsdu_maximum_size_r2i",
1513 &hf_protocol_version_1,
1515 "Protocol Version 1",
1516 "ses.protocol_version1",
1525 &hf_protocol_version_2,
1527 "Protocol Version 2",
1528 "ses.protocol_version2",
1537 &hf_initial_serial_number,
1539 "Initial Serial Number",
1540 "ses.initial_serial_number",
1541 FT_STRING, BASE_NONE,
1549 &hf_beginning_of_SSDU,
1551 "beginning of SSDU",
1552 "ses.begininng_of_SSDU",
1573 &hf_release_token_setting,
1575 "release token setting",
1576 "ses.release_token_setting",
1578 VALS(token_setting_vals),
1585 &hf_major_activity_token_setting,
1587 "major/activity setting",
1588 "ses.major_activity_token_setting",
1590 VALS(token_setting_vals),
1592 "major/activity token setting",
1597 &hf_synchronize_minor_token_setting,
1599 "synchronize-minor token setting",
1600 "ses.synchronize_minor_token_setting",
1602 VALS(token_setting_vals),
1609 &hf_data_token_setting,
1611 "data token setting",
1612 "ses.data_token_setting",
1614 VALS(token_setting_vals),
1621 &hf_activity_identifier,
1623 "Activity Identifier",
1624 "ses.activity_identifier",
1625 FT_UINT32, BASE_DEC,
1636 "ses.serial_number",
1637 FT_STRING, BASE_NONE,
1645 &hf_calling_session_selector,
1647 "Calling Session Selector",
1648 "ses.calling_session_selector",
1649 FT_BYTES, BASE_NONE,
1657 &hf_called_session_selector,
1659 "Called Session Selector",
1660 "ses.called_session_selector",
1661 FT_BYTES, BASE_NONE,
1669 &hf_second_serial_number,
1671 "Second Serial Number",
1672 "ses.second_serial_number",
1673 FT_STRING, BASE_NONE,
1681 &hf_second_initial_serial_number,
1683 "Second Initial Serial Number",
1684 "ses.second_initial_serial_number",
1685 FT_STRING, BASE_NONE,
1693 &hf_large_initial_serial_number,
1695 "Large Initial Serial Number",
1696 "ses.large_initial_serial_number",
1697 FT_STRING, BASE_NONE,
1705 &hf_large_second_initial_serial_number,
1707 "Large Second Initial Serial Number",
1708 "ses.large_second_initial_serial_number",
1709 FT_STRING, BASE_NONE,
1717 &hf_connect_protocol_options_flags,
1720 "ses.connect.flags",
1730 &hf_version_number_options_flags,
1734 "ses.version.flags",
1745 &hf_token_item_options_flags,
1749 "ses.tken_item.flags",
1760 &hf_enclosure_item_options_flags,
1764 "ses.enclosure.flags",
1775 static gint *ett[] =
1779 &ett_connect_protocol_options_flags,
1780 &ett_protocol_version_flags,
1781 &ett_enclosure_item_flags,
1782 &ett_token_item_flags,
1783 &ett_ses_req_options_flags,
1785 /* module_t *ses_module; */
1788 proto_ses = proto_register_protocol(PROTO_STRING_SES, "SES", "ses");
1789 proto_register_field_array(proto_ses, hf, array_length(hf));
1790 proto_register_subtree_array(ett, array_length(ett));
1793 ses_module = prefs_register_protocol(proto_ses, NULL);
1795 prefs_register_bool_preference(ses_module, "desegment",
1796 "Reassemble session packets ",
1797 "Whether the session dissector should reassemble messages spanning multiple SES segments",
1801 * Register the dissector by name, so other dissectors can
1802 * grab it by name rather than just referring to it directly
1803 * (you can't refer to it directly from a plugin dissector
1804 * on Windows without stuffing it into the Big Transfer Vector).
1806 register_dissector("ses", dissect_ses, proto_ses);
1810 dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1812 /* must check that this really is a ses packet */
1818 /* first, check do we have at least 4 bytes (type+length) */
1819 if (tvb_length(tvb) < 2)
1820 return FALSE; /* no */
1822 /* can we recognize session PDU ? Return FALSE if not */
1824 type = tvb_get_guint8(tvb, offset);
1825 /* check SPDU type */
1826 if (match_strval(type, ses_vals) == NULL)
1828 return FALSE; /* no, it isn't a session PDU */
1831 /* can we recognize the second session PDU if the first one was
1832 * a Give Tokens PDU? Return FALSE if not */
1833 if(tvb_bytes_exist(tvb, 2, 2) && type == SES_GIVE_TOKENS) {
1835 type = tvb_get_guint8(tvb, offset+2);
1836 /* check SPDU type */
1837 if (match_strval(type, ses_vals) == NULL)
1839 return FALSE; /* no, it isn't a session PDU */
1843 /* some Siemens SIMATIC protocols also use COTP, and shouldn't be
1844 * misinterpreted as SES.
1845 * the starter in this case is fixed to 0x32 (SES_MINOR_SYNC_ACK for SES),
1846 * so if the parameter type is unknown, it's probably SIMATIC */
1847 if(type == 0x32 && tvb_length(tvb) >= 3) {
1848 type = tvb_get_guint8(tvb, offset+2);
1849 if (match_strval(type, param_vals) == NULL) {
1850 return FALSE; /* it's probably a SIMATIC protocol */
1854 /* OK,let's check SPDU length */
1855 /* get length of SPDU */
1856 len = get_item_len(tvb, offset+1, &len_len);
1858 /* add header length */
1860 /* do we have enough bytes ? */
1861 if (tvb_length(tvb) < len)
1862 return FALSE; /* no */
1864 dissect_ses(tvb, pinfo, parent_tree);
1869 proto_reg_handoff_ses(void)
1871 /* find data dissector */
1872 data_handle = find_dissector("data");
1874 /* define sub dissector */
1875 pres_handle = find_dissector("pres");
1877 /* add our session dissector to cotp dissector list
1878 * and cotp_is dissector list*/
1879 heur_dissector_add("cotp", dissect_ses_heur, proto_ses);
1880 heur_dissector_add("cotp_is", dissect_ses_heur, proto_ses);