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.
34 #include <epan/packet.h>
35 #include <epan/prefs.h>
36 #include <epan/asn1.h>
37 #include <epan/conversation.h>
38 #include <epan/reassemble.h>
40 #include "packet-ber.h"
41 #include "packet-ses.h"
42 #include "packet-frame.h"
44 /* #include <epan/prefs.h> */
45 #include <epan/emem.h>
46 #include <epan/strutil.h>
48 /* ses header fields */
49 static int proto_ses = -1;
50 static int hf_ses_type = -1;
51 static int hf_ses_type_0 = -1;
52 static int hf_ses_length = -1;
53 static int hf_ses_version = -1;
54 static int hf_ses_reserved = -1;
56 static int hf_ses_segment_data = -1;
57 static int hf_ses_segments = -1;
58 static int hf_ses_segment = -1;
59 static int hf_ses_segment_overlap = -1;
60 static int hf_ses_segment_overlap_conflicts = -1;
61 static int hf_ses_segment_multiple_tails = -1;
62 static int hf_ses_segment_too_long_segment = -1;
63 static int hf_ses_segment_error = -1;
64 static int hf_ses_segment_count = -1;
65 static int hf_ses_reassembled_in = -1;
66 static int hf_ses_reassembled_length = -1;
68 /* ses fields defining a sub tree */
69 static gint ett_ses = -1;
70 static gint ett_ses_param = -1;
72 static gint ett_ses_segment = -1;
73 static gint ett_ses_segments = -1;
77 static int hf_connect_protocol_options_flags = -1;
78 static int hf_version_number_options_flags = -1;
79 static int hf_enclosure_item_options_flags = -1;
80 static int hf_token_item_options_flags = -1;
82 static gint ett_connect_protocol_options_flags = -1;
83 static gint ett_protocol_version_flags = -1;
84 static gint ett_enclosure_item_flags = -1;
85 static gint ett_token_item_flags = -1;
86 static gint ett_ses_req_options_flags = -1;
88 /* called SS user reference */
89 static int hf_called_ss_user_reference = -1;
91 /* calling SS user reference */
92 static int hf_calling_ss_user_reference = -1;
94 /* common reference */
95 static int hf_common_reference = -1;
97 /* additional reference information */
98 static int hf_additional_reference_information = -1;
101 static int hf_release_token = -1;
102 static int hf_major_activity_token = -1;
103 static int hf_synchronize_minor_token = -1;
104 static int hf_data_token = -1;
106 /* protocol options */
107 static int hf_able_to_receive_extended_concatenated_SPDU = -1;
109 /* session requirement */
110 static int hf_session_user_req_flags = -1;
111 static int hf_session_exception_report= -1;
112 static int hf_data_separation_function_unit= -1;
113 static int hf_symmetric_synchronize_function_unit= -1;
114 static int hf_typed_data_function_unit= -1;
115 static int hf_exception_function_unit= -1;
116 static int hf_capability_function_unit=-1;
117 static int hf_negotiated_release_function_unit= -1;
118 static int hf_activity_management_function_unit= -1;
119 static int hf_resynchronize_function_unit= -1;
120 static int hf_major_resynchronize_function_unit= -1;
121 static int hf_minor_resynchronize_function_unit= -1;
122 static int hf_expedited_data_resynchronize_function_unit= -1;
123 static int hf_duplex_function_unit= -1;
124 static int hf_half_duplex_function_unit = -1;
126 /* TSDU maximum size */
127 static int hf_proposed_tsdu_maximum_size_i2r = -1;
128 static int hf_proposed_tsdu_maximum_size_r2i = -1;
130 /* protocol version */
131 static int hf_protocol_version_1 = -1;
132 static int hf_protocol_version_2 = -1;
134 /* initial serial number */
135 static int hf_initial_serial_number = -1;
138 static int hf_beginning_of_SSDU = -1;
139 static int hf_end_of_SSDU = -1;
141 /* token setting item */
143 static const value_string token_setting_vals[] = {
144 { 0x00, "initiator's side" },
145 { 0x01, "responder's side" },
146 { 0x02, "called SS user's choice" },
147 { 0x03, "reserved" },
151 static int hf_release_token_setting = -1;
152 static int hf_major_activity_token_setting = -1;
153 static int hf_synchronize_minor_token_setting = -1;
154 static int hf_data_token_setting = -1;
156 /* calling session selector */
157 static int hf_calling_session_selector = -1;
159 /* called session selector */
160 static int hf_called_session_selector = -1;
163 static int hf_activity_identifier = -1;
166 static int hf_serial_number = -1;
168 /* second serial number */
169 static int hf_second_serial_number = -1;
171 /* second initial serial number */
172 static int hf_second_initial_serial_number = -1;
174 /* large initial serial number */
175 static int hf_large_initial_serial_number = -1;
177 /* large second initial serial number */
178 static int hf_large_second_initial_serial_number = -1;
180 /* clses header fields */
181 static int proto_clses = -1;
183 #define PROTO_STRING_CLSES "ISO 9548-1 OSI Connectionless Session Protocol"
185 static dissector_handle_t pres_handle = NULL;
187 static GHashTable *ses_fragment_table = NULL;
188 static GHashTable *ses_reassembled_table = NULL;
190 static const fragment_items ses_frag_items = {
191 /* Segment subtrees */
197 &hf_ses_segment_overlap,
198 &hf_ses_segment_overlap_conflicts,
199 &hf_ses_segment_multiple_tails,
200 &hf_ses_segment_too_long_segment,
201 &hf_ses_segment_error,
202 &hf_ses_segment_count,
203 /* Reassembled in field */
204 &hf_ses_reassembled_in,
205 /* Reassembled length field */
206 &hf_ses_reassembled_length,
212 const value_string ses_vals[] =
214 {SES_CONNECTION_REQUEST, "CONNECT (CN) SPDU" }, /* 13 */
215 {SES_CONNECTION_ACCEPT, "ACCEPT (AC) SPDU" }, /* 14 */
216 {SES_EXCEPTION_REPORT, "EXCEPTION REPORT (ER) SPDU" }, /* 0 */
217 {SES_DATA_TRANSFER, "DATA TRANSFER (DT) SPDU" }, /* 1 */
218 {SES_PLEASE_TOKENS, "PLEASE TOKENS (PT) SPDU" }, /* 2 */
219 {SES_EXPEDITED, "EXPEDITED (EX) SPDU" }, /* 5 */
220 {SES_PREPARE, "PREPARE (PR) SPDU" }, /* 7 */
221 {SES_NOT_FINISHED, "NOT FINISHED (NF) SPDU" }, /* 8 */
222 {SES_FINISH, "FINISH (FN) SPDU" }, /* 9 */
223 {SES_DISCONNECT, "DISCONNECT (DN) SPDU" }, /* 10 */
224 {SES_REFUSE, "REFUSE (RF) SPDU" }, /* 12 */
225 {SES_CONNECTION_DATA_OVERFLOW, "CONNECT DATA OVERFLOW (CDO) SPDU"}, /* 15 */
226 {SES_OVERFLOW_ACCEPT, "OVERFLOW ACCEPT (OA) SPDU" }, /* 16 */
227 {SES_GIVE_TOKENS_CONFIRM, "GIVE TOKENS CONFIRM (GTC) SPDU"}, /* 21 */
228 {SES_GIVE_TOKENS_ACK, "GIVE TOKENS ACK (GTA) SPDU" }, /* 22 */
229 {SES_ABORT, "ABORT (AB) SPDU" }, /* 25 */
230 {SES_ABORT_ACCEPT, "ABORT ACCEPT (AA) SPDU" }, /* 26 */
231 {SES_ACTIVITY_RESUME, "ACTIVITY RESUME (AR) SPDU" }, /* 29 */
232 {SES_TYPED_DATA, "TYPED DATA (TD) SPDU" }, /* 33 */
233 {SES_RESYNCHRONIZE_ACK, "RESYNCHRONIZE ACK (RA) SPDU" }, /* 34 */
234 {SES_MAJOR_SYNC_POINT, "MAJOR SYNC POINT (MAP) SPDU" }, /* 41 */
235 {SES_MAJOR_SYNC_ACK, "MAJOR SYNC ACK (MAA) SPDU" }, /* 42 */
236 {SES_ACTIVITY_START, "ACTIVITY START (AS) SPDU" }, /* 45 */
237 {SES_EXCEPTION_DATA, "EXCEPTION DATA (ED) SPDU" }, /* 48 */
238 {SES_MINOR_SYNC_POINT, "MINOR SYNC POINT (MIP) SPDU" }, /* 49 */
239 {SES_MINOR_SYNC_ACK, "MINOR SYNC ACK (MIA) SPDU" }, /* 50 */
240 {SES_RESYNCHRONIZE, "RESYNCHRONIZE (RS) SPDU" }, /* 53 */
241 {SES_ACTIVITY_DISCARD, "ACTIVITY DISCARD (AD) SPDU" }, /* 57 */
242 {SES_ACTIVITY_DISCARD_ACK, "ACTIVITY DISCARD ACK (ADA) SPDU" }, /* 58 */
243 {SES_CAPABILITY, "CAPABILITY DATA (CD) SPDU" }, /* 61 */
244 {SES_CAPABILITY_DATA_ACK, "CAPABILITY DATA ACK (CDA) SPDU" }, /* 62 */
245 {CLSES_UNIT_DATA, "UNIT DATA (UD) SPDU" }, /* 64 */
249 static const value_string ses_category0_vals[] =
251 {SES_PLEASE_TOKENS, "Please tokens PDU" },
252 {SES_GIVE_TOKENS, "Give tokens PDU" },
257 static const value_string param_vals[] =
259 {Connection_Identifier, "Connection Identifier"},
260 {Connect_Accept_Item, "Connect Accept Item"},
261 {Called_SS_user_Reference, "Called SS user Reference"},
262 {Calling_SS_user_Reference, "Calling SS user Reference"},
263 {Common_Reference, "Common Reference"},
264 {Sync_Type_Item, "Sync Type Item"},
265 {Token_Item, "Token Item"},
266 {Transport_Disconnect, "Transport_Disconnect"},
267 {Additional_Reference_Information, "Additional Reference Information"},
268 {Protocol_Options, "Protocol Options"},
269 {TSDU_Maximum_Size, "TSDU Maximum Size"},
270 {Version_Number, "Version Number"},
271 {Initial_Serial_Number, "Initial Serial Number"},
272 {Prepare_Type, "Prepare Type"},
273 {EnclosureItem, "Enclosure Item"},
274 {Token_Setting_Item, "Token Setting Item"},
275 {Resync_Type, "Resync Type"},
276 {Activity_Identifier, "Activity Identifier"},
277 {Serial_Number, "Serial Number"},
278 {Linking_Information, "Linking Information"},
279 {Reflect_Parameter, "Reflect Parameter"},
280 {Reason_Code, "Reason Code"},
281 {Calling_Session_Selector, "Calling Session Selector"},
282 {Called_Session_Selector, "Called Session Selector"},
283 {Second_Resync_Type, "Second Resync Type"},
284 {Second_Serial_Number, "Second Serial Number"},
285 {Second_Initial_Serial_Number, "Second Initial Serial Number"},
286 {Upper_Limit_Serial_Number, "Upper Limit Serial Number"},
287 {Large_Initial_Serial_Number, "Large Initial Serial Number"},
288 {Large_Second_Initial_Serial_Number, "Large Second Initial Serial Number"},
289 {Data_Overflow, "Data Overflow"},
290 {Session_Requirement, "Session Requirement"},
291 {User_Data, "Session user data"},
292 {Extended_User_Data, "Session extended user data"},
296 static const value_string reason_vals[] =
298 {reason_not_specified, "Rejection by called SS-user; reason not specified" },
299 {temporary_congestion, "Rejection by called SS-user due to temporary congestion" },
300 {Subsequent, "Rejection by called SS-user." },
301 {Session_Selector_unknown, "Session Selector unknown" },
302 {SS_user_not_attached_to_SSAP, "SS-user not attached to SSAP" },
303 {SPM_congestion_at_connect_time, "SPM congestion at connect time" },
304 {versions_not_supported, "Proposed protocol versions not supported" },
305 {SPM_reason_not_specified, "Rejection by the SPM; reason not specified" },
306 {SPM_implementation_restriction, "Finish PDU" },
307 {SES_DISCONNECT, "Rejection by the SPM; implementation restriction stated in the PICS" },
311 /* desegmentation of OSI over ses */
312 static gboolean ses_desegment = TRUE;
314 /* RTSE reassembly data */
315 static guint ses_pres_ctx_id = 0;
316 static gboolean ses_rtse_reassemble = FALSE;
318 /* find the dissector for data */
319 static dissector_handle_t data_handle;
322 call_pres_dissector(tvbuff_t *tvb, int offset, guint16 param_len,
323 packet_info *pinfo, proto_tree *tree,
324 proto_tree *param_tree,
325 struct SESSION_DATA_STRUCTURE *session)
327 void *saved_private_data;
329 /* do we have OSI presentation packet dissector ? */
332 /* No - display as data */
335 proto_tree_add_text(param_tree, tvb, offset, param_len,
341 /* Yes - call presentation dissector */
344 next_tvb = tvb_new_subset(tvb, offset, param_len, param_len);
345 /* save type of session pdu. We'll need it in the presentation dissector */
346 saved_private_data = pinfo->private_data;
347 pinfo->private_data = session;
350 call_dissector(pres_handle, next_tvb, pinfo, tree);
354 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
357 /* Restore private_data even if there was an exception */
358 pinfo->private_data = saved_private_data;
362 /* this routine returns length of parameter field, parameter group,
365 get_item_len(tvbuff_t *tvb, int offset, int *len_len)
369 len = tvb_get_guint8(tvb, offset);
370 if(len == TWO_BYTE_LEN)
372 len = tvb_get_ntohs(tvb, offset+1);
381 dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree,
382 proto_tree *param_tree, packet_info *pinfo, guint8 param_type,
383 guint16 param_len, guint8 *enclosure_item_flags,
384 struct SESSION_DATA_STRUCTURE *session)
386 gboolean has_user_information = TRUE;
389 proto_tree *flags_tree;
391 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
395 case Called_SS_user_Reference:
400 proto_tree_add_item(param_tree,
401 hf_called_ss_user_reference,
402 tvb, offset, param_len, ENC_NA);
406 case Calling_SS_user_Reference:
411 proto_tree_add_item(param_tree,
412 hf_calling_ss_user_reference,
413 tvb, offset, param_len, ENC_NA);
417 case Common_Reference:
422 proto_tree_add_item(param_tree,
424 tvb, offset, param_len, ENC_NA);
428 case Additional_Reference_Information:
433 proto_tree_add_item(param_tree,
434 hf_additional_reference_information,
435 tvb, offset, param_len, ENC_NA);
442 proto_tree_add_text(param_tree, tvb, offset,
443 param_len, "Length is %u, should be 1",
449 flags = tvb_get_guint8(tvb, offset);
450 tf = proto_tree_add_uint(param_tree,
451 hf_token_item_options_flags, tvb, offset, 1,
453 flags_tree = proto_item_add_subtree(tf,
454 ett_token_item_flags);
455 proto_tree_add_boolean(flags_tree, hf_release_token,
456 tvb, offset, 1, flags);
457 proto_tree_add_boolean(flags_tree,
458 hf_major_activity_token, tvb, offset, 1, flags);
459 proto_tree_add_boolean(flags_tree,
460 hf_synchronize_minor_token, tvb, offset, 1, flags);
461 proto_tree_add_boolean(flags_tree, hf_data_token, tvb,
466 case Transport_Disconnect:
469 proto_tree_add_text(param_tree, tvb, offset,
470 param_len, "Length is %u, should be 1",
478 flags8 = tvb_get_guint8(tvb, offset);
479 if(flags8 & transport_connection_is_released )
481 proto_tree_add_text(param_tree, tvb, offset, 1,
482 "transport connection is released");
486 proto_tree_add_text(param_tree, tvb, offset, 1,
487 "transport connection is kept");
490 if(flags8 & user_abort )
492 proto_tree_add_text(param_tree, tvb, offset, 1,
494 session->abort_type = SESSION_USER_ABORT;
498 session->abort_type = SESSION_PROVIDER_ABORT;
501 if(flags8 & protocol_error )
503 proto_tree_add_text(param_tree, tvb, offset, 1,
507 if(flags8 & no_reason )
509 proto_tree_add_text(param_tree, tvb, offset, 1,
513 if(flags8 & implementation_restriction )
515 proto_tree_add_text(param_tree, tvb, offset, 1,
516 "implementation restriction");
521 case Protocol_Options:
524 proto_tree_add_text(param_tree, tvb, offset,
525 param_len, "Length is %u, should be 1",
531 flags = tvb_get_guint8(tvb, offset);
532 tf = proto_tree_add_uint(param_tree,
533 hf_connect_protocol_options_flags, tvb, offset, 1,
535 flags_tree = proto_item_add_subtree(tf,
536 ett_connect_protocol_options_flags);
537 proto_tree_add_boolean(flags_tree,
538 hf_able_to_receive_extended_concatenated_SPDU,
539 tvb, offset, 1, flags);
543 case Session_Requirement:
546 proto_tree_add_text(param_tree, tvb, offset,
547 param_len, "Length is %u, should be 2",
553 flags = tvb_get_ntohs(tvb, offset);
554 tf = proto_tree_add_uint(param_tree,
555 hf_session_user_req_flags, tvb, offset, 2,
557 flags_tree = proto_item_add_subtree(tf,
558 ett_ses_req_options_flags);
559 proto_tree_add_boolean(flags_tree,
560 hf_session_exception_report, tvb, offset, 2, flags);
561 proto_tree_add_boolean(flags_tree,
562 hf_data_separation_function_unit, tvb, offset, 2,
564 proto_tree_add_boolean(flags_tree,
565 hf_symmetric_synchronize_function_unit,
566 tvb, offset, 2, flags);
567 proto_tree_add_boolean(flags_tree,
568 hf_typed_data_function_unit, tvb, offset, 2, flags);
569 proto_tree_add_boolean(flags_tree,
570 hf_exception_function_unit, tvb, offset, 2, flags);
571 proto_tree_add_boolean(flags_tree,
572 hf_capability_function_unit, tvb, offset, 2, flags);
573 proto_tree_add_boolean(flags_tree,
574 hf_negotiated_release_function_unit,
575 tvb, offset, 2, flags);
576 proto_tree_add_boolean(flags_tree,
577 hf_activity_management_function_unit,
578 tvb, offset, 2, flags);
579 proto_tree_add_boolean(flags_tree,
580 hf_resynchronize_function_unit, tvb, offset, 2,
582 proto_tree_add_boolean(flags_tree,
583 hf_major_resynchronize_function_unit,
584 tvb, offset, 2, flags);
585 proto_tree_add_boolean(flags_tree,
586 hf_minor_resynchronize_function_unit,
587 tvb, offset, 2, flags);
588 proto_tree_add_boolean(flags_tree,
589 hf_expedited_data_resynchronize_function_unit,
590 tvb, offset, 2, flags);
591 proto_tree_add_boolean(flags_tree,
592 hf_duplex_function_unit, tvb, offset, 2, flags);
593 proto_tree_add_boolean(flags_tree,
594 hf_half_duplex_function_unit,
595 tvb, offset, 2, flags);
599 case TSDU_Maximum_Size:
602 proto_tree_add_text(param_tree, tvb, offset,
603 param_len, "Length is %u, should be 4",
609 proto_tree_add_item(param_tree,
610 hf_proposed_tsdu_maximum_size_i2r,
611 tvb, offset, 2, FALSE);
612 proto_tree_add_item(param_tree,
613 hf_proposed_tsdu_maximum_size_r2i,
614 tvb, offset+2, 2, FALSE);
621 proto_tree_add_text(param_tree, tvb, offset,
622 param_len, "Length is %u, should be 1",
628 flags = tvb_get_guint8(tvb, offset);
629 tf = proto_tree_add_uint(param_tree,
630 hf_version_number_options_flags, tvb, offset, 1,
632 flags_tree = proto_item_add_subtree(tf,
633 ett_protocol_version_flags);
634 proto_tree_add_boolean(flags_tree,
635 hf_protocol_version_2, tvb, offset, 1, flags);
636 proto_tree_add_boolean(flags_tree,
637 hf_protocol_version_1, tvb, offset, 1, flags);
641 case Initial_Serial_Number:
646 proto_tree_add_item(param_tree,
647 hf_initial_serial_number,
648 tvb, offset, param_len, FALSE);
655 proto_tree_add_text(param_tree, tvb, offset,
656 param_len, "Length is %u, should be 1",
660 flags = tvb_get_guint8(tvb, offset);
661 *enclosure_item_flags = (guint8) flags;
664 tf = proto_tree_add_uint(param_tree,
665 hf_enclosure_item_options_flags, tvb, offset, 1,
667 flags_tree = proto_item_add_subtree(tf,
668 ett_enclosure_item_flags);
669 proto_tree_add_boolean(flags_tree, hf_end_of_SSDU,
670 tvb, offset, 1, flags);
671 proto_tree_add_boolean(flags_tree, hf_beginning_of_SSDU,
672 tvb, offset, 1, flags);
674 if (flags & END_SPDU) {
676 * In Data Transfer and Typed Data SPDUs, (X.225: 8.3.{11,13}.4)
677 * "The User Information Field shall be present
678 * if the Enclosure Item is not present, or has
679 * bit 2 = 0", which presumably means it shall
680 * *not* be present if the Enclosure item *is*
681 * present and has bit 2 = 1.
684 if(!(flags & BEGINNING_SPDU)) {
685 /* X.225 7.11.2 also states:
686 * "All DATA TRANSFER SPDUs, except the last DATA TRANSFER SPDU in a sequence greater than one, must have user information"
687 * So if BEGINNING_SPDU and END_SPDU are set in the enclosure item, then this is presumably a sequence of one and
688 * consequently there must be user information.
690 * So, there is only no user information if *only* END_SPDU is set.
693 has_user_information = FALSE;
698 case Token_Setting_Item:
701 proto_tree_add_text(param_tree, tvb, offset,
702 param_len, "Length is %u, should be 1",
708 proto_tree_add_item(param_tree,
709 hf_release_token_setting,
710 tvb, offset, 1, FALSE);
711 proto_tree_add_item(param_tree,
712 hf_major_activity_token_setting,
713 tvb, offset, 1, FALSE);
714 proto_tree_add_item(param_tree,
715 hf_synchronize_minor_token_setting,
716 tvb, offset, 1, FALSE);
717 proto_tree_add_item(param_tree,
718 hf_data_token_setting,
719 tvb, offset, 1, FALSE);
723 case Activity_Identifier:
728 dissect_ber_integer(FALSE, &asn1_ctx, param_tree, tvb, offset,
729 hf_activity_identifier, NULL);
738 proto_tree_add_item(param_tree,
740 tvb, offset, param_len, FALSE);
746 0: Rejection by called SS-user; reason not specified.
747 1: Rejection by called SS-user due to temporary congestion.
748 2: Rejection by called SS-user. Subsequent octets may be used for user data
749 up to a length of 512 octets if Protocol Version 1 has been selected, and up
750 to a length such that the total length (including SI and LI) of the SPDU
751 does not exceed 65 539 octets if Protocol Version 2 has been selected.
752 128 + 1: Session Selector unknown.
753 128 + 2: SS-user not attached to SSAP.
754 128 + 3: SPM congestion at connect time.
755 128 + 4: Proposed protocol versions not supported.
756 128 + 5: Rejection by the SPM; reason not specified.
757 128 + 6: Rejection by the SPM; implementation restriction stated in the
761 proto_tree_add_text(param_tree, tvb, offset,
762 param_len, "Length is %u, should be >= 1",
770 reason_code = tvb_get_guint8(tvb, offset);
771 proto_tree_add_text(param_tree, tvb, offset, 1,
773 val_to_str(reason_code, reason_vals, "Unknown (%u)"));
779 call_pres_dissector(tvb, offset, param_len,
780 pinfo, tree, param_tree, session);
784 case Calling_Session_Selector:
789 proto_tree_add_item(param_tree,
790 hf_calling_session_selector,
791 tvb, offset, param_len, ENC_NA);
795 case Called_Session_Selector:
800 proto_tree_add_item(param_tree,
801 hf_called_session_selector,
802 tvb, offset, param_len, ENC_NA);
806 case Second_Serial_Number:
811 proto_tree_add_item(param_tree,
812 hf_second_serial_number,
813 tvb, offset, param_len, FALSE);
817 case Second_Initial_Serial_Number:
822 proto_tree_add_item(param_tree,
823 hf_second_initial_serial_number,
824 tvb, offset, param_len, FALSE);
828 case Large_Initial_Serial_Number:
833 proto_tree_add_item(param_tree,
834 hf_large_initial_serial_number,
835 tvb, offset, param_len, FALSE);
839 case Large_Second_Initial_Serial_Number:
844 proto_tree_add_item(param_tree,
845 hf_large_second_initial_serial_number,
846 tvb, offset, param_len, FALSE);
853 return has_user_information;
857 dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree,
858 proto_tree *pg_tree, packet_info *pinfo, guint16 pg_len,
859 guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session)
861 gboolean has_user_information = TRUE;
863 proto_tree *param_tree;
865 const char *param_str;
871 param_type = tvb_get_guint8(tvb, offset);
872 ti = proto_tree_add_text(pg_tree, tvb, offset, -1, "%s",
873 val_to_str(param_type, param_vals,
874 "Unknown parameter type (0x%02x)"));
875 param_tree = proto_item_add_subtree(ti, ett_ses_param);
876 param_str = val_to_str_const(param_type, param_vals, "Unknown");
877 proto_tree_add_text(param_tree, tvb, offset, 1,
878 "Parameter type: %s", param_str);
881 param_len = get_item_len(tvb, offset, &len_len);
882 if (len_len > pg_len) {
883 proto_item_set_len(ti, pg_len + 1);
884 proto_tree_add_text(param_tree, tvb, offset, pg_len,
885 "Parameter length doesn't fit in parameter");
886 return has_user_information;
889 if (param_len > pg_len) {
890 proto_item_set_len(ti, pg_len + 1 + len_len);
891 proto_tree_add_text(param_tree, tvb, offset, pg_len,
892 "Parameter length: %u, should be <= %u",
894 return has_user_information;
896 proto_item_set_len(ti, 1 + len_len + param_len);
897 proto_tree_add_text(param_tree, tvb, offset, len_len,
898 "Parameter length: %u", param_len);
901 if (param_str != NULL)
905 /* PG's in PG's are invalid, presumably */
906 case Extended_User_Data:
908 case Connect_Accept_Item:
909 case Connection_Identifier:
910 case Linking_Information:
911 proto_tree_add_text(param_tree, tvb, offset,
913 "Parameter group inside parameter group");
917 if (!dissect_parameter(tvb, offset, tree,
918 param_tree, pinfo, param_type, param_len,
919 enclosure_item_flags, session))
920 has_user_information = FALSE;
927 return has_user_information;
931 * Returns TRUE if there's a User Information field in this SPDU, FALSE
935 dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree,
936 proto_tree *ses_tree, packet_info *pinfo,
937 guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session)
939 gboolean has_user_information = TRUE;
941 proto_tree *param_tree;
943 const char *param_str;
949 param_type = tvb_get_guint8(tvb, offset);
950 ti = proto_tree_add_text(ses_tree, tvb, offset, -1, "%s",
951 val_to_str(param_type, param_vals,
952 "Unknown parameter type (0x%02x)"));
953 param_tree = proto_item_add_subtree(ti, ett_ses_param);
954 param_str = val_to_str_const(param_type, param_vals, "Unknown");
955 proto_tree_add_text(param_tree, tvb, offset, 1,
956 "Parameter type: %s", param_str);
959 param_len = get_item_len(tvb, offset, &len_len);
961 proto_item_set_len(ti, len + 1 );
962 proto_tree_add_text(param_tree, tvb, offset, len,
963 "Parameter length doesn't fit in parameter");
964 return has_user_information;
967 if (param_len > len) {
968 proto_item_set_len(ti, len + 1 + len_len);
969 proto_tree_add_text(param_tree, tvb, offset, len,
970 "Parameter length: %u, should be <= %u",
972 return has_user_information;
974 proto_item_set_len(ti, 1 + len_len + param_len);
975 proto_tree_add_text(param_tree, tvb, offset, len_len,
976 "Parameter length: %u", param_len);
979 if (param_str != NULL)
983 case Extended_User_Data:
984 call_pres_dissector(tvb, offset, param_len,
985 pinfo, tree, param_tree, session);
989 call_pres_dissector(tvb, offset, param_len,
990 pinfo, tree, param_tree, session);
994 case Connect_Accept_Item:
995 case Connection_Identifier:
996 case Linking_Information:
998 if (!dissect_parameter_group(tvb, offset, tree,
999 param_tree, pinfo, param_len, enclosure_item_flags, session))
1000 has_user_information = FALSE;
1003 /* everything else is a PI */
1005 if (!dissect_parameter(tvb, offset, tree,
1006 param_tree, pinfo, param_type, param_len,
1007 enclosure_item_flags, session))
1008 has_user_information = FALSE;
1012 offset += param_len;
1015 return has_user_information;
1022 dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
1023 gboolean tokens, gboolean connectionless)
1025 gboolean has_user_information = FALSE;
1027 proto_item *ti = NULL;
1028 proto_tree *ses_tree = NULL;
1030 guint16 parameters_len;
1031 tvbuff_t *next_tvb = NULL;
1032 void *save_private_data;
1033 guint32 *pres_ctx_id = NULL;
1034 guint8 enclosure_item_flags = BEGINNING_SPDU|END_SPDU;
1035 struct SESSION_DATA_STRUCTURE session;
1040 type = tvb_get_guint8(tvb, offset);
1041 session.spdu_type = type;
1042 session.abort_type = SESSION_NO_ABORT;
1044 session.rtse_reassemble = FALSE;
1046 if(connectionless) {
1047 col_add_str(pinfo->cinfo, COL_INFO,
1048 val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
1050 ti = proto_tree_add_item(tree, proto_clses, tvb, offset,
1052 ses_tree = proto_item_add_subtree(ti, ett_ses);
1053 proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
1056 has_user_information = TRUE;
1059 col_add_str(pinfo->cinfo, COL_INFO,
1060 val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)"));
1062 ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
1064 ses_tree = proto_item_add_subtree(ti, ett_ses);
1065 proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb,
1069 col_add_str(pinfo->cinfo, COL_INFO,
1070 val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
1072 ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
1074 ses_tree = proto_item_add_subtree(ti, ett_ses);
1075 proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
1080 * Might this SPDU have a User Information field?
1083 case SES_DATA_TRANSFER:
1085 case SES_TYPED_DATA:
1086 has_user_information = TRUE;
1088 case SES_MAJOR_SYNC_POINT:
1089 pres_ctx_id = p_get_proto_data (pinfo->fd, proto_ses);
1090 if (ses_rtse_reassemble != 0 && !pres_ctx_id) {
1091 /* First time visited - save pres_ctx_id */
1092 pres_ctx_id = se_alloc (sizeof (guint32));
1093 *pres_ctx_id = ses_pres_ctx_id;
1094 p_add_proto_data (pinfo->fd, proto_ses, pres_ctx_id);
1097 session.pres_ctx_id = *pres_ctx_id;
1098 session.rtse_reassemble = TRUE;
1099 has_user_information = TRUE;
1101 ses_rtse_reassemble = FALSE;
1107 /* get length of SPDU parameter field */
1108 parameters_len = get_item_len(tvb, offset, &len_len);
1110 proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset,
1111 len_len, parameters_len);
1114 /* Dissect parameters. */
1115 if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree,
1116 pinfo, &enclosure_item_flags, &session))
1117 has_user_information = FALSE;
1118 offset += parameters_len;
1120 proto_item_set_end(ti, tvb, offset);
1122 /* Dissect user information, if present */
1123 if (!ses_desegment || enclosure_item_flags == (BEGINNING_SPDU|END_SPDU)) {
1124 if (has_user_information) {
1125 /* Not desegment or only one segment */
1126 if (tvb_reported_length_remaining(tvb, offset) > 0 || type == SES_MAJOR_SYNC_POINT) {
1127 next_tvb = tvb_new_subset_remaining(tvb, offset);
1131 conversation_t *conversation = NULL;
1132 fragment_data *frag_msg = NULL;
1136 /* Use conversation index as segment id */
1137 conversation = find_conversation (pinfo->fd->num,
1138 &pinfo->src, &pinfo->dst, pinfo->ptype,
1139 pinfo->srcport, pinfo->destport, 0);
1140 if (conversation != NULL) {
1141 ses_id = conversation->index;
1143 fragment_len = tvb_reported_length_remaining (tvb, offset);
1144 ti = proto_tree_add_item (ses_tree, hf_ses_segment_data, tvb, offset,
1145 fragment_len, ENC_NA);
1146 proto_item_append_text (ti, " (%d byte%s)", fragment_len, plurality (fragment_len, "", "s"));
1147 frag_msg = fragment_add_seq_next (tvb, offset, pinfo,
1148 ses_id, ses_fragment_table,
1149 ses_reassembled_table, fragment_len,
1150 (enclosure_item_flags & END_SPDU) ? FALSE : TRUE);
1151 next_tvb = process_reassembled_data (tvb, offset, pinfo, "Reassembled SES",
1152 frag_msg, &ses_frag_items, NULL,
1153 (enclosure_item_flags & END_SPDU) ? tree : ses_tree);
1155 has_user_information = TRUE;
1156 offset += fragment_len;
1159 if (has_user_information && next_tvb) {
1161 call_dissector(data_handle, next_tvb, pinfo, tree);
1163 /* save type of session pdu. We'll need it in the presentation dissector */
1164 save_private_data = pinfo->private_data;
1165 pinfo->private_data = &session;
1166 call_dissector(pres_handle, next_tvb, pinfo, tree);
1167 pinfo->private_data = save_private_data;
1171 * No more SPDUs to dissect. Set the offset to the
1172 * end of the tvbuff.
1174 offset = tvb_length(tvb);
1175 if (session.rtse_reassemble && type == SES_DATA_TRANSFER) {
1176 ses_pres_ctx_id = session.pres_ctx_id;
1177 ses_rtse_reassemble = TRUE;
1184 * Dissect SPDUs inside a TSDU.
1187 dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1191 gboolean is_clsp = FALSE;
1193 type = tvb_get_guint8(tvb, offset);
1194 if(type == CLSES_UNIT_DATA)
1198 col_set_str(pinfo->cinfo, COL_PROTOCOL, is_clsp ? "CLSES" : "SES");
1199 col_clear(pinfo->cinfo, COL_INFO);
1203 * Do we have a category 0 SPDU (GIVE_TOKENS/PLEASE_TOKENS) as
1206 * If so, dissect it as such (GIVE_TOKENS and DATA_TRANSFER have
1207 * the same SPDU type value).
1209 if ((type == SES_PLEASE_TOKENS) || (type == SES_GIVE_TOKENS))
1210 offset = dissect_spdu(tvb, offset, pinfo, tree, TOKENS_SPDU, FALSE);
1213 /* Dissect the remaining SPDUs. */
1214 while (tvb_reported_length_remaining(tvb, offset) > 0)
1215 offset = dissect_spdu(tvb, offset, pinfo, tree, NON_TOKENS_SPDU, is_clsp);
1218 static void ses_reassemble_init (void)
1220 fragment_table_init (&ses_fragment_table);
1221 reassembled_table_init (&ses_reassembled_table);
1225 proto_register_ses(void)
1227 static hf_register_info hf[] =
1248 VALS(ses_category0_vals),
1291 &hf_called_ss_user_reference,
1293 "Called SS User Reference",
1294 "ses.called_ss_user_reference",
1295 FT_BYTES, BASE_NONE,
1303 &hf_calling_ss_user_reference,
1305 "Calling SS User Reference",
1306 "ses.calling_ss_user_reference",
1307 FT_BYTES, BASE_NONE,
1315 &hf_common_reference,
1318 "ses.common_reference",
1319 FT_BYTES, BASE_NONE,
1327 &hf_additional_reference_information,
1329 "Additional Reference Information",
1330 "ses.additional_reference_information",
1331 FT_BYTES, BASE_NONE,
1342 "ses.release_token",
1351 &hf_major_activity_token,
1353 "major/activity token",
1357 MAJOR_ACTIVITY_TOKEN,
1363 &hf_synchronize_minor_token,
1365 "synchronize minor token",
1366 "ses.synchronize_token",
1369 SYNCHRONIZE_MINOR_TOKEN,
1387 &hf_able_to_receive_extended_concatenated_SPDU,
1389 "Able to receive extended concatenated SPDU",
1399 &hf_session_user_req_flags,
1412 &hf_session_exception_report,
1414 "Session exception report",
1415 "ses.exception_report.",
1418 SES_EXCEPTION_REPORT,
1424 &hf_data_separation_function_unit,
1426 "Data separation function unit",
1430 DATA_SEPARATION_FUNCTION_UNIT,
1436 &hf_symmetric_synchronize_function_unit,
1438 "Symmetric synchronize function unit",
1442 SYMMETRIC_SYNCHRONIZE_FUNCTION_UNIT,
1448 &hf_typed_data_function_unit,
1450 "Typed data function unit",
1454 TYPED_DATA_FUNCTION_UNIT,
1460 &hf_exception_function_unit,
1462 "Exception function unit",
1463 "ses.exception_data",
1466 EXCEPTION_FUNCTION_UNIT,
1472 &hf_capability_function_unit,
1474 "Capability function unit",
1475 "ses.capability_data",
1478 CAPABILITY_DATA_FUNCTION_UNIT,
1484 &hf_negotiated_release_function_unit,
1486 "Negotiated release function unit",
1487 "ses.negotiated_release",
1490 NEGOTIATED_RELEASE_FUNCTION_UNIT,
1496 &hf_activity_management_function_unit,
1498 "Activity management function unit",
1499 "ses.activity_management",
1502 ACTIVITY_MANAGEMENT_FUNCTION_UNIT,
1508 &hf_resynchronize_function_unit,
1510 "Resynchronize function unit",
1511 "ses.resynchronize",
1514 RESYNCHRONIZE_FUNCTION_UNIT,
1520 &hf_major_resynchronize_function_unit,
1522 "Major resynchronize function unit",
1523 "ses.major_resynchronize",
1526 MAJOR_SYNCHRONIZE_FUNCTION_UNIT,
1532 &hf_minor_resynchronize_function_unit,
1534 "Minor resynchronize function unit",
1535 "ses.minor_resynchronize",
1538 MINOR_SYNCHRONIZE_FUNCTION_UNIT,
1544 &hf_expedited_data_resynchronize_function_unit,
1546 "Expedited data function unit",
1547 "ses.expedited_data",
1550 EXPEDITED_DATA_FUNCTION_UNIT,
1556 &hf_duplex_function_unit,
1558 "Duplex functional unit",
1562 DUPLEX_FUNCTION_UNIT,
1568 &hf_half_duplex_function_unit,
1570 "Half-duplex functional unit",
1574 HALF_DUPLEX_FUNCTION_UNIT,
1580 &hf_proposed_tsdu_maximum_size_i2r,
1582 "Proposed TSDU Maximum Size, Initiator to Responder",
1583 "ses.proposed_tsdu_maximum_size_i2r",
1593 &hf_proposed_tsdu_maximum_size_r2i,
1595 "Proposed TSDU Maximum Size, Responder to Initiator",
1596 "ses.proposed_tsdu_maximum_size_r2i",
1606 &hf_protocol_version_1,
1608 "Protocol Version 1",
1609 "ses.protocol_version1",
1618 &hf_protocol_version_2,
1620 "Protocol Version 2",
1621 "ses.protocol_version2",
1630 &hf_initial_serial_number,
1632 "Initial Serial Number",
1633 "ses.initial_serial_number",
1634 FT_STRING, BASE_NONE,
1642 &hf_beginning_of_SSDU,
1644 "beginning of SSDU",
1645 "ses.begininng_of_SSDU",
1666 &hf_release_token_setting,
1668 "release token setting",
1669 "ses.release_token_setting",
1671 VALS(token_setting_vals),
1678 &hf_major_activity_token_setting,
1680 "major/activity setting",
1681 "ses.major_activity_token_setting",
1683 VALS(token_setting_vals),
1685 "major/activity token setting",
1690 &hf_synchronize_minor_token_setting,
1692 "synchronize-minor token setting",
1693 "ses.synchronize_minor_token_setting",
1695 VALS(token_setting_vals),
1702 &hf_data_token_setting,
1704 "data token setting",
1705 "ses.data_token_setting",
1707 VALS(token_setting_vals),
1714 &hf_activity_identifier,
1716 "Activity Identifier",
1717 "ses.activity_identifier",
1718 FT_UINT32, BASE_DEC,
1729 "ses.serial_number",
1730 FT_STRING, BASE_NONE,
1738 &hf_calling_session_selector,
1740 "Calling Session Selector",
1741 "ses.calling_session_selector",
1742 FT_BYTES, BASE_NONE,
1750 &hf_called_session_selector,
1752 "Called Session Selector",
1753 "ses.called_session_selector",
1754 FT_BYTES, BASE_NONE,
1762 &hf_second_serial_number,
1764 "Second Serial Number",
1765 "ses.second_serial_number",
1766 FT_STRING, BASE_NONE,
1774 &hf_second_initial_serial_number,
1776 "Second Initial Serial Number",
1777 "ses.second_initial_serial_number",
1778 FT_STRING, BASE_NONE,
1786 &hf_large_initial_serial_number,
1788 "Large Initial Serial Number",
1789 "ses.large_initial_serial_number",
1790 FT_STRING, BASE_NONE,
1798 &hf_large_second_initial_serial_number,
1800 "Large Second Initial Serial Number",
1801 "ses.large_second_initial_serial_number",
1802 FT_STRING, BASE_NONE,
1810 &hf_connect_protocol_options_flags,
1813 "ses.connect.flags",
1823 &hf_version_number_options_flags,
1827 "ses.version.flags",
1838 &hf_token_item_options_flags,
1842 "ses.tken_item.flags",
1853 &hf_enclosure_item_options_flags,
1857 "ses.enclosure.flags",
1867 { &hf_ses_segment_data,
1868 { "SES segment data", "ses.segment.data", FT_NONE, BASE_NONE,
1869 NULL, 0x00, NULL, HFILL } },
1871 { "SES segments", "ses.segments", FT_NONE, BASE_NONE,
1872 NULL, 0x00, NULL, HFILL } },
1874 { "SES segment", "ses.segment", FT_FRAMENUM, BASE_NONE,
1875 NULL, 0x00, NULL, HFILL } },
1876 { &hf_ses_segment_overlap,
1877 { "SES segment overlap", "ses.segment.overlap", FT_BOOLEAN,
1878 BASE_NONE, NULL, 0x0, NULL, HFILL } },
1879 { &hf_ses_segment_overlap_conflicts,
1880 { "SES segment overlapping with conflicting data",
1881 "ses.segment.overlap.conflicts", FT_BOOLEAN, BASE_NONE,
1882 NULL, 0x0, NULL, HFILL } },
1883 { &hf_ses_segment_multiple_tails,
1884 { "SES has multiple tail segments",
1885 "ses.segment.multiple_tails", FT_BOOLEAN, BASE_NONE,
1886 NULL, 0x0, NULL, HFILL } },
1887 { &hf_ses_segment_too_long_segment,
1888 { "SES segment too long", "ses.segment.too_long_segment",
1889 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1890 { &hf_ses_segment_error,
1891 { "SES desegmentation error", "ses.segment.error", FT_FRAMENUM,
1892 BASE_NONE, NULL, 0x00, NULL, HFILL } },
1893 { &hf_ses_segment_count,
1894 { "SES segment count", "ses.segment.count", FT_UINT32, BASE_DEC,
1895 NULL, 0x00, NULL, HFILL } },
1896 { &hf_ses_reassembled_in,
1897 { "Reassembled SES in frame", "ses.reassembled.in", FT_FRAMENUM, BASE_NONE,
1898 NULL, 0x00, "This SES packet is reassembled in this frame", HFILL } },
1899 { &hf_ses_reassembled_length,
1900 { "Reassembled SES length", "ses.reassembled.length", FT_UINT32, BASE_DEC,
1901 NULL, 0x00, "The total length of the reassembled payload", HFILL } }
1904 static gint *ett[] =
1908 &ett_connect_protocol_options_flags,
1909 &ett_protocol_version_flags,
1910 &ett_enclosure_item_flags,
1911 &ett_token_item_flags,
1912 &ett_ses_req_options_flags,
1916 module_t *ses_module;
1918 proto_ses = proto_register_protocol(PROTO_STRING_SES, "SES", "ses");
1919 proto_register_field_array(proto_ses, hf, array_length(hf));
1920 proto_register_subtree_array(ett, array_length(ett));
1922 register_init_routine (&ses_reassemble_init);
1924 ses_module = prefs_register_protocol(proto_ses, NULL);
1926 prefs_register_bool_preference(ses_module, "desegment",
1927 "Reassemble session packets ",
1928 "Whether the session dissector should reassemble messages spanning multiple SES segments",
1932 * Register the dissector by name, so other dissectors can
1933 * grab it by name rather than just referring to it directly
1934 * (you can't refer to it directly from a plugin dissector
1935 * on Windows without stuffing it into the Big Transfer Vector).
1937 register_dissector("ses", dissect_ses, proto_ses);
1941 dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1943 /* must check that this really is a ses packet */
1949 /* first, check do we have at least 4 bytes (type+length) */
1950 if (tvb_length(tvb) < 2)
1951 return FALSE; /* no */
1953 /* can we recognize session PDU ? Return FALSE if not */
1955 type = tvb_get_guint8(tvb, offset);
1956 /* check SPDU type */
1957 if (match_strval(type, ses_vals) == NULL)
1959 return FALSE; /* no, it isn't a session PDU */
1962 /* can we recognize the second session PDU if the first one was
1963 * a Give Tokens PDU? Return FALSE if not */
1964 if(tvb_bytes_exist(tvb, 2, 2) && type == SES_GIVE_TOKENS) {
1966 type = tvb_get_guint8(tvb, offset+2);
1967 /* check SPDU type */
1968 if (match_strval(type, ses_vals) == NULL)
1970 return FALSE; /* no, it isn't a session PDU */
1974 /* some Siemens SIMATIC protocols also use COTP, and shouldn't be
1975 * misinterpreted as SES.
1976 * the starter in this case is fixed to 0x32 (SES_MINOR_SYNC_ACK for SES),
1977 * so if the parameter type is unknown, it's probably SIMATIC */
1978 if(type == 0x32 && tvb_length(tvb) >= 3) {
1979 type = tvb_get_guint8(tvb, offset+2);
1980 if (match_strval(type, param_vals) == NULL) {
1981 return FALSE; /* it's probably a SIMATIC protocol */
1985 /* OK,let's check SPDU length */
1986 /* get length of SPDU */
1987 len = get_item_len(tvb, offset+1, &len_len);
1989 /* add header length */
1991 /* do we have enough bytes ? */
1992 if (tvb_length(tvb) < len)
1993 return FALSE; /* no */
1995 /* final check to see if the next SPDU, if present, is also valid */
1996 if (tvb_length(tvb) > len) {
1997 type = tvb_get_guint8(tvb, offset + len + 1);
1998 /* check SPDU type */
1999 if (match_strval(type, ses_vals) == NULL) {
2000 return FALSE; /* no, it isn't a session PDU */
2004 dissect_ses(tvb, pinfo, parent_tree);
2009 proto_reg_handoff_ses(void)
2011 /* find data dissector */
2012 data_handle = find_dissector("data");
2014 /* define sub dissector */
2015 pres_handle = find_dissector("pres");
2017 /* add our session dissector to cotp dissector list
2018 * and cotp_is dissector list*/
2019 heur_dissector_add("cotp", dissect_ses_heur, proto_ses);
2020 heur_dissector_add("cotp_is", dissect_ses_heur, proto_ses);
2025 void proto_register_clses(void)
2027 proto_clses = proto_register_protocol(PROTO_STRING_CLSES, "CLSP", "clsp");
2031 proto_reg_handoff_clses(void)
2033 /* add our session dissector to cltp dissector list */
2034 heur_dissector_add("cltp", dissect_ses_heur, proto_clses);