Use ENC_NA as encoding for proto_tree_add_item() calls which directly reference an...
[obnox/wireshark/wip.git] / epan / dissectors / packet-ses.c
1 /* packet-ses.c
2 *
3 * Routine to dissect ITU-T Rec. X.225 (1995 E)/ISO 8327-1 OSI Session Protocol packets
4 *
5 * $Id$
6 *
7 * Yuriy Sidelnikov <YSidelnikov@hotmail.com>
8 *
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
12 *
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.
17 *
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.
22 *
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.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <glib.h>
33
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>
39
40 #include "packet-ber.h"
41 #include "packet-ses.h"
42 #include "packet-frame.h"
43
44 /* #include <epan/prefs.h> */
45 #include <epan/emem.h>
46 #include <epan/strutil.h>
47
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;
55
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;
67
68 /* ses fields defining a sub tree */
69 static gint ett_ses           = -1;
70 static gint ett_ses_param     = -1;
71
72 static gint ett_ses_segment = -1;
73 static gint ett_ses_segments = -1;
74
75
76 /* flags */
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;
81
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;
87
88 /* called SS user reference */
89 static int hf_called_ss_user_reference = -1;
90
91 /* calling SS user reference */
92 static int hf_calling_ss_user_reference = -1;
93
94 /* common reference */
95 static int hf_common_reference = -1;
96
97 /* additional reference information */
98 static int hf_additional_reference_information = -1;
99
100 /* token item */
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;
105
106 /* protocol options */
107 static int hf_able_to_receive_extended_concatenated_SPDU = -1;
108
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;
125
126 /* TSDU maximum size */
127 static int hf_proposed_tsdu_maximum_size_i2r = -1;
128 static int hf_proposed_tsdu_maximum_size_r2i = -1;
129
130 /* protocol version */
131 static int hf_protocol_version_1 = -1;
132 static int hf_protocol_version_2 = -1;
133
134 /* initial serial number */
135 static int hf_initial_serial_number = -1;
136
137 /* enclosure item */
138 static int hf_beginning_of_SSDU = -1;
139 static int hf_end_of_SSDU = -1;
140
141 /* token setting item */
142
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" },
148         { 0, NULL }
149 };
150
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;
155
156 /* calling session selector */
157 static int hf_calling_session_selector = -1;
158
159 /* called session selector */
160 static int hf_called_session_selector = -1;
161
162 /* activity id */
163 static int hf_activity_identifier = -1;
164
165 /* serial number */
166 static int hf_serial_number = -1;
167
168 /* second serial number */
169 static int hf_second_serial_number = -1;
170
171 /* second initial serial number */
172 static int hf_second_initial_serial_number = -1;
173
174 /* large initial serial number */
175 static int hf_large_initial_serial_number = -1;
176
177 /* large second initial serial number */
178 static int hf_large_second_initial_serial_number = -1;
179
180 /* clses header fields             */
181 static int proto_clses          = -1;
182
183 #define PROTO_STRING_CLSES "ISO 9548-1 OSI Connectionless Session Protocol"
184
185 static dissector_handle_t pres_handle = NULL;
186
187 static GHashTable *ses_fragment_table = NULL;
188 static GHashTable *ses_reassembled_table = NULL;
189
190 static const fragment_items ses_frag_items = {
191   /* Segment subtrees */
192   &ett_ses_segment,
193   &ett_ses_segments,
194   /* Segment fields */
195   &hf_ses_segments,
196   &hf_ses_segment,
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,
207   /* Tag */
208   "SES segments"
209 };
210
211
212 const value_string ses_vals[] =
213 {
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 */
246   {0,                                   NULL }
247 };
248
249 static const value_string ses_category0_vals[] =
250 {
251   {SES_PLEASE_TOKENS,   "Please tokens PDU" },
252   {SES_GIVE_TOKENS,     "Give tokens PDU" },
253   {0,                   NULL }
254 };
255
256
257 static const value_string param_vals[] =
258 {
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"},
293   {0, NULL}
294 };
295
296 static const value_string reason_vals[] =
297 {
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"   },
308   {0,             NULL           }
309 };
310
311 /* desegmentation of OSI over ses  */
312 static gboolean ses_desegment = TRUE;
313
314 /* RTSE reassembly data */
315 static guint ses_pres_ctx_id = 0;
316 static gboolean ses_rtse_reassemble = FALSE;
317
318 /* find the dissector for data */
319 static dissector_handle_t data_handle;
320
321 static void
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)
326 {
327         void *saved_private_data;
328
329         /* do we have OSI presentation packet dissector ? */
330         if(!pres_handle)
331         {
332                 /* No - display as data */
333                 if (tree)
334                 {
335                         proto_tree_add_text(param_tree, tvb, offset, param_len,
336                             "User data");
337                 }
338         }
339         else
340         {
341                 /* Yes - call presentation dissector */
342                 tvbuff_t *next_tvb;
343
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;
348                 TRY
349                 {
350                         call_dissector(pres_handle, next_tvb, pinfo, tree);
351                 }
352                 CATCH_ALL
353                 {
354                         show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
355                 }
356                 ENDTRY;
357                 /* Restore private_data even if there was an exception */
358                 pinfo->private_data = saved_private_data;
359         }
360 }
361
362 /* this routine returns length of parameter field, parameter group,
363    or parameter */
364 static int
365 get_item_len(tvbuff_t *tvb, int offset, int *len_len)
366 {
367         guint16 len;
368
369         len = tvb_get_guint8(tvb, offset);
370         if(len == TWO_BYTE_LEN)
371         {
372                 len = tvb_get_ntohs(tvb, offset+1);
373                 *len_len = 3;
374         }
375         else
376                 *len_len = 1;
377         return len;
378 }
379
380 static gboolean
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)
385 {
386         gboolean has_user_information = TRUE;
387         guint16       flags;
388         proto_item   *tf;
389         proto_tree   *flags_tree;
390         asn1_ctx_t asn1_ctx;
391         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
392
393         switch (param_type)
394         {
395         case Called_SS_user_Reference:
396                 if (param_len == 0)
397                         break;
398                 if (tree)
399                 {
400                         proto_tree_add_item(param_tree,
401                             hf_called_ss_user_reference,
402                             tvb, offset, param_len, ENC_NA);
403                 }
404                 break;
405
406         case Calling_SS_user_Reference:
407                 if (param_len == 0)
408                         break;
409                 if (tree)
410                 {
411                         proto_tree_add_item(param_tree,
412                             hf_calling_ss_user_reference,
413                             tvb, offset, param_len, ENC_NA);
414                 }
415                 break;
416
417         case Common_Reference:
418                 if (param_len == 0)
419                         break;
420                 if (tree)
421                 {
422                         proto_tree_add_item(param_tree,
423                             hf_common_reference,
424                             tvb, offset, param_len, ENC_NA);
425                 }
426                 break;
427
428         case Additional_Reference_Information:
429                 if (param_len == 0)
430                         break;
431                 if (tree)
432                 {
433                         proto_tree_add_item(param_tree,
434                             hf_additional_reference_information,
435                             tvb, offset, param_len, ENC_NA);
436                 }
437                 break;
438
439         case Token_Item:
440                 if (param_len != 1)
441                 {
442                         proto_tree_add_text(param_tree, tvb, offset,
443                             param_len, "Length is %u, should be 1",
444                             param_len);
445                         break;
446                 }
447                 if (tree)
448                 {
449                         flags = tvb_get_guint8(tvb, offset);
450                         tf = proto_tree_add_uint(param_tree,
451                             hf_token_item_options_flags, tvb, offset, 1,
452                             flags);
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,
462                             offset, 1, flags);
463                 }
464                 break;
465
466         case Transport_Disconnect:
467                 if (param_len != 1)
468                 {
469                         proto_tree_add_text(param_tree, tvb, offset,
470                             param_len, "Length is %u, should be 1",
471                             param_len);
472                         break;
473                 }
474                 if (tree)
475                 {
476                         guint8       flags8;
477
478                         flags8 = tvb_get_guint8(tvb, offset);
479                         if(flags8 & transport_connection_is_released )
480                         {
481                                 proto_tree_add_text(param_tree, tvb, offset, 1,
482                                     "transport connection is released");
483                         }
484                         else
485                         {
486                                 proto_tree_add_text(param_tree, tvb, offset, 1,
487                                     "transport connection is kept");
488                         }
489
490                         if(flags8 & user_abort )
491                         {
492                                 proto_tree_add_text(param_tree, tvb, offset, 1,
493                                     "user abort");
494                                 session->abort_type = SESSION_USER_ABORT;
495                         }
496                         else
497                         {
498                                 session->abort_type = SESSION_PROVIDER_ABORT;
499                         }
500
501                         if(flags8 & protocol_error )
502                         {
503                                 proto_tree_add_text(param_tree, tvb, offset, 1,
504                                     "protocol error");
505                         }
506
507                         if(flags8 & no_reason )
508                         {
509                                 proto_tree_add_text(param_tree, tvb, offset, 1,
510                                     "no reason");
511                         }
512
513                         if(flags8 & implementation_restriction )
514                         {
515                                 proto_tree_add_text(param_tree, tvb, offset, 1,
516                                     "implementation restriction");
517                         }
518                 }
519                 break;
520
521         case Protocol_Options:
522                 if (param_len != 1)
523                 {
524                         proto_tree_add_text(param_tree, tvb, offset,
525                             param_len, "Length is %u, should be 1",
526                             param_len);
527                         break;
528                 }
529                 if (tree)
530                 {
531                         flags = tvb_get_guint8(tvb, offset);
532                         tf = proto_tree_add_uint(param_tree,
533                             hf_connect_protocol_options_flags, tvb, offset, 1,
534                             flags);
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);
540                 }
541                 break;
542
543         case Session_Requirement:
544                 if (param_len != 2)
545                 {
546                         proto_tree_add_text(param_tree, tvb, offset,
547                             param_len, "Length is %u, should be 2",
548                             param_len);
549                         break;
550                 }
551                 if (tree)
552                 {
553                         flags = tvb_get_ntohs(tvb, offset);
554                         tf = proto_tree_add_uint(param_tree,
555                             hf_session_user_req_flags, tvb, offset, 2,
556                             flags);
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,
563                             flags);
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,
581                             flags);
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);
596                 }
597                 break;
598
599         case TSDU_Maximum_Size:
600                 if (param_len != 4)
601                 {
602                         proto_tree_add_text(param_tree, tvb, offset,
603                             param_len, "Length is %u, should be 4",
604                             param_len);
605                         break;
606                 }
607                 if (tree)
608                 {
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);
615                 }
616                 break;
617
618         case Version_Number:
619                 if (param_len != 1)
620                 {
621                         proto_tree_add_text(param_tree, tvb, offset,
622                             param_len, "Length is %u, should be 1",
623                             param_len);
624                         break;
625                 }
626                 if (tree)
627                 {
628                         flags = tvb_get_guint8(tvb, offset);
629                         tf = proto_tree_add_uint(param_tree,
630                             hf_version_number_options_flags, tvb, offset, 1,
631                             flags);
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);
638                 }
639                 break;
640
641         case Initial_Serial_Number:
642                 if (param_len == 0)
643                         break;
644                 if (tree)
645                 {
646                         proto_tree_add_item(param_tree,
647                             hf_initial_serial_number,
648                             tvb, offset, param_len, FALSE);
649                 }
650                 break;
651
652         case EnclosureItem:
653                 if (param_len != 1)
654                 {
655                         proto_tree_add_text(param_tree, tvb, offset,
656                             param_len, "Length is %u, should be 1",
657                             param_len);
658                         break;
659                 }
660                 flags = tvb_get_guint8(tvb, offset);
661                 *enclosure_item_flags = (guint8) flags;
662                 if (tree)
663                 {
664                         tf = proto_tree_add_uint(param_tree,
665                             hf_enclosure_item_options_flags, tvb, offset, 1,
666                             flags);
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);
673                 }
674                 if (flags & END_SPDU) {
675                         /*
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.
682                          */
683
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.
689                      *
690                      * So, there is only no user information if *only* END_SPDU is set.
691                      */
692
693                      has_user_information = FALSE;
694                   }
695                 }
696                 break;
697
698         case Token_Setting_Item:
699                 if (param_len != 1)
700                 {
701                         proto_tree_add_text(param_tree, tvb, offset,
702                             param_len, "Length is %u, should be 1",
703                             param_len);
704                         break;
705                 }
706                 if (tree)
707                 {
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);
720                 }
721                 break;
722
723         case Activity_Identifier:
724                 if (param_len == 0)
725                         break;
726                 if (tree)
727                 {
728                         dissect_ber_integer(FALSE, &asn1_ctx, param_tree, tvb, offset,
729                             hf_activity_identifier, NULL);
730                 }
731                 break;
732
733         case Serial_Number:
734                 if (param_len == 0)
735                         break;
736                 if (tree)
737                 {
738                         proto_tree_add_item(param_tree,
739                             hf_serial_number,
740                             tvb, offset, param_len, FALSE);
741                 }
742                 break;
743
744         case Reason_Code:
745 /*
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
758 PICS.    */
759                 if (param_len < 1)
760                 {
761                         proto_tree_add_text(param_tree, tvb, offset,
762                             param_len, "Length is %u, should be >= 1",
763                             param_len);
764                         break;
765                 }
766                 if (tree)
767                 {
768                         guint8      reason_code;
769
770                         reason_code = tvb_get_guint8(tvb, offset);
771                         proto_tree_add_text(param_tree, tvb, offset, 1,
772                             "Reason Code: %s",
773                             val_to_str(reason_code, reason_vals, "Unknown (%u)"));
774                 }
775                 offset++;
776                 param_len--;
777                 if (param_len != 0)
778                 {
779                         call_pres_dissector(tvb, offset, param_len,
780                             pinfo, tree, param_tree, session);
781                 }
782                 break;
783
784         case Calling_Session_Selector:
785                 if (param_len == 0)
786                         break;
787                 if (tree)
788                 {
789                         proto_tree_add_item(param_tree,
790                             hf_calling_session_selector,
791                             tvb, offset, param_len, ENC_NA);
792                 }
793                 break;
794
795         case Called_Session_Selector:
796                 if (param_len == 0)
797                         break;
798                 if (tree)
799                 {
800                         proto_tree_add_item(param_tree,
801                             hf_called_session_selector,
802                             tvb, offset, param_len, ENC_NA);
803                 }
804                 break;
805
806         case Second_Serial_Number:
807                 if (param_len == 0)
808                         break;
809                 if (tree)
810                 {
811                         proto_tree_add_item(param_tree,
812                             hf_second_serial_number,
813                             tvb, offset, param_len, FALSE);
814                 }
815                 break;
816
817         case Second_Initial_Serial_Number:
818                 if (param_len == 0)
819                         break;
820                 if (tree)
821                 {
822                         proto_tree_add_item(param_tree,
823                             hf_second_initial_serial_number,
824                             tvb, offset, param_len, FALSE);
825                 }
826                 break;
827
828         case Large_Initial_Serial_Number:
829                 if (param_len == 0)
830                         break;
831                 if (tree)
832                 {
833                         proto_tree_add_item(param_tree,
834                             hf_large_initial_serial_number,
835                             tvb, offset, param_len, FALSE);
836                 }
837                 break;
838
839         case Large_Second_Initial_Serial_Number:
840                 if (param_len == 0)
841                         break;
842                 if (tree)
843                 {
844                         proto_tree_add_item(param_tree,
845                             hf_large_second_initial_serial_number,
846                             tvb, offset, param_len, FALSE);
847                 }
848                 break;
849
850         default:
851                 break;
852         }
853         return has_user_information;
854 }
855
856 static gboolean
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)
860 {
861         gboolean has_user_information = TRUE;
862         proto_item *ti;
863         proto_tree *param_tree;
864         guint8 param_type;
865         const char *param_str;
866         int len_len;
867         guint16 param_len;
868
869         while(pg_len != 0)
870         {
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);
879                 offset++;
880                 pg_len--;
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;
887                 }
888                 pg_len -= len_len;
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",
893                             param_len, pg_len);
894                         return has_user_information;
895                 }
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);
899                 offset += len_len;
900
901                 if (param_str != NULL)
902                 {
903                         switch(param_type)
904                         {
905                         /* PG's in PG's are invalid, presumably */
906                         case Extended_User_Data:
907                         case User_Data:
908                         case Connect_Accept_Item:
909                         case Connection_Identifier:
910                         case Linking_Information:
911                                 proto_tree_add_text(param_tree, tvb, offset,
912                                     param_len,
913                                     "Parameter group inside parameter group");
914                                 break;
915
916                         default:
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;
921                                 break;
922                         }
923                 }
924                 offset += param_len;
925                 pg_len -= param_len;
926         }
927         return has_user_information;
928 }
929
930 /*
931  * Returns TRUE if there's a User Information field in this SPDU, FALSE
932  * otherwise.
933  */
934 static gboolean
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)
938 {
939         gboolean has_user_information = TRUE;
940         proto_item *ti;
941         proto_tree *param_tree;
942         guint8 param_type;
943         const char *param_str;
944         int len_len;
945         guint16 param_len;
946
947         while (len != 0)
948         {
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);
957                 offset++;
958                 len--;
959                 param_len = get_item_len(tvb, offset, &len_len);
960                 if (len_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;
965                 }
966                 len -= len_len;
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",
971                             param_len, len);
972                         return has_user_information;
973                 }
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);
977                 offset += len_len;
978
979                 if (param_str != NULL)
980                 {
981                         switch(param_type)
982                         {
983                         case Extended_User_Data:
984                                 call_pres_dissector(tvb, offset, param_len,
985                                     pinfo, tree, param_tree, session);
986                                 break;
987
988                         case User_Data:
989                                 call_pres_dissector(tvb, offset, param_len,
990                                     pinfo, tree, param_tree, session);
991                                 break;
992
993                         /* handle PGI's  */
994                         case Connect_Accept_Item:
995                         case Connection_Identifier:
996                         case Linking_Information:
997                                 /* Yes. */
998                                 if (!dissect_parameter_group(tvb, offset, tree,
999                                     param_tree, pinfo, param_len, enclosure_item_flags, session))
1000                                         has_user_information = FALSE;
1001                                 break;
1002
1003                         /* everything else is a PI */
1004                         default:
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;
1009                                 break;
1010                         }
1011                 }
1012                 offset += param_len;
1013                 len -= param_len;
1014         }
1015         return has_user_information;
1016 }
1017
1018 /*
1019  * Dissect an SPDU.
1020  */
1021 static int
1022 dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
1023              gboolean tokens, gboolean connectionless)
1024 {
1025         gboolean has_user_information = FALSE;
1026         guint8 type;
1027         proto_item *ti = NULL;
1028         proto_tree *ses_tree = NULL;
1029         int len_len;
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;
1036
1037         /*
1038          * Get SPDU type.
1039          */
1040         type = tvb_get_guint8(tvb, offset);
1041         session.spdu_type = type;
1042         session.abort_type = SESSION_NO_ABORT;
1043         session.ros_op = 0;
1044         session.rtse_reassemble = FALSE;
1045
1046         if(connectionless) {
1047                 col_add_str(pinfo->cinfo, COL_INFO,
1048                             val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
1049                 if (tree) {
1050                         ti = proto_tree_add_item(tree, proto_clses, tvb, offset,
1051                                 -1, FALSE);
1052                         ses_tree = proto_item_add_subtree(ti, ett_ses);
1053                         proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
1054                                 offset, 1, type);
1055                 }
1056                 has_user_information = TRUE;
1057         }
1058         else if (tokens) {
1059                 col_add_str(pinfo->cinfo, COL_INFO,
1060                             val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)"));
1061                 if (tree) {
1062                         ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
1063                             -1, FALSE);
1064                         ses_tree = proto_item_add_subtree(ti, ett_ses);
1065                         proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb,
1066                             offset, 1, type);
1067                 }
1068         } else {
1069                 col_add_str(pinfo->cinfo, COL_INFO,
1070                             val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
1071                 if (tree) {
1072                         ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
1073                                 -1, FALSE);
1074                         ses_tree = proto_item_add_subtree(ti, ett_ses);
1075                         proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
1076                                 offset, 1, type);
1077                 }
1078
1079                 /*
1080                  * Might this SPDU have a User Information field?
1081                  */
1082                 switch (type) {
1083                 case SES_DATA_TRANSFER:
1084                 case SES_EXPEDITED:
1085                 case SES_TYPED_DATA:
1086                         has_user_information = TRUE;
1087                         break;
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);
1095                         }
1096                         if (pres_ctx_id) {
1097                                 session.pres_ctx_id = *pres_ctx_id;
1098                                 session.rtse_reassemble = TRUE;
1099                                 has_user_information = TRUE;
1100                         }
1101                         ses_rtse_reassemble = FALSE;
1102                         break;
1103                 }
1104         }
1105         offset++;
1106
1107         /* get length of SPDU parameter field */
1108         parameters_len = get_item_len(tvb, offset, &len_len);
1109         if (tree)
1110                 proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset,
1111                     len_len, parameters_len);
1112         offset += len_len;
1113
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;
1119
1120         proto_item_set_end(ti, tvb, offset);
1121
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);
1128                         }
1129                 }
1130         } else {
1131                 conversation_t *conversation = NULL;
1132                 fragment_data *frag_msg = NULL;
1133                 gint fragment_len;
1134                 guint32 ses_id = 0;
1135
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;
1142                 }
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);
1154
1155                 has_user_information = TRUE;
1156                 offset += fragment_len;
1157         }
1158
1159         if (has_user_information && next_tvb) {
1160                 if (!pres_handle) {
1161                         call_dissector(data_handle, next_tvb, pinfo, tree);
1162                 } else {
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;
1168                 }
1169
1170                 /*
1171                  * No more SPDUs to dissect.  Set the offset to the
1172                  * end of the tvbuff.
1173                  */
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;
1178                 }
1179         }
1180         return offset;
1181 }
1182
1183 /*
1184  * Dissect SPDUs inside a TSDU.
1185  */
1186 static void
1187 dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1188 {
1189         int offset = 0;
1190         guint8 type;
1191         gboolean is_clsp = FALSE;
1192
1193         type = tvb_get_guint8(tvb, offset);
1194         if(type == CLSES_UNIT_DATA)
1195                 is_clsp = TRUE;
1196
1197
1198         col_set_str(pinfo->cinfo, COL_PROTOCOL, is_clsp ? "CLSES" : "SES");
1199         col_clear(pinfo->cinfo, COL_INFO);
1200
1201
1202         /*
1203          * Do we have a category 0 SPDU (GIVE_TOKENS/PLEASE_TOKENS) as
1204          * the first SPDU?
1205          *
1206          * If so, dissect it as such (GIVE_TOKENS and DATA_TRANSFER have
1207          * the same SPDU type value).
1208          */
1209         if ((type == SES_PLEASE_TOKENS) || (type == SES_GIVE_TOKENS))
1210                 offset = dissect_spdu(tvb, offset, pinfo, tree, TOKENS_SPDU, FALSE);
1211
1212
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);
1216 }
1217
1218 static void ses_reassemble_init (void)
1219 {
1220         fragment_table_init (&ses_fragment_table);
1221         reassembled_table_init (&ses_reassembled_table);
1222 }
1223
1224 void
1225 proto_register_ses(void)
1226 {
1227         static hf_register_info hf[] =
1228         {
1229                 {
1230                         &hf_ses_type,
1231                         {
1232                                 "SPDU Type",
1233                                 "ses.type",
1234                                 FT_UINT8,
1235                                 BASE_DEC,
1236                                 VALS(ses_vals),
1237                                 0x0,
1238                                 NULL, HFILL
1239                         }
1240                 },
1241                 {
1242                         &hf_ses_type_0,
1243                         {
1244                                 "SPDU Type",
1245                                 "ses.type",
1246                                 FT_UINT8,
1247                                 BASE_DEC,
1248                                 VALS(ses_category0_vals),
1249                                 0x0,
1250                                 NULL, HFILL
1251                         }
1252                 },
1253                 {
1254                         &hf_ses_length,
1255                         {
1256                                 "Length",
1257                                 "ses.length",
1258                                 FT_UINT16,
1259                                 BASE_DEC,
1260                                 NULL,
1261                                 0x0,
1262                                 NULL, HFILL
1263                         }
1264                 },
1265
1266                 {
1267                         &hf_ses_version,
1268                         {
1269                                 "Version",
1270                                 "ses.version",
1271                                 FT_UINT8,
1272                                 BASE_DEC,
1273                                 NULL,
1274                                 0x0,
1275                                 NULL, HFILL
1276                         }
1277                 },
1278                 {
1279                         &hf_ses_reserved,
1280                         {
1281                                 "Reserved",
1282                                 "ses.reserved",
1283                                 FT_UINT8,
1284                                 BASE_DEC,
1285                                 NULL,
1286                                 0x0,
1287                                 NULL, HFILL
1288                         }
1289                 },
1290                 {
1291                         &hf_called_ss_user_reference,
1292                         {
1293                                 "Called SS User Reference",
1294                                 "ses.called_ss_user_reference",
1295                                 FT_BYTES, BASE_NONE,
1296                                 NULL,
1297                                 0x0,
1298                                 NULL,
1299                                 HFILL
1300                         }
1301                 },
1302                 {
1303                         &hf_calling_ss_user_reference,
1304                         {
1305                                 "Calling SS User Reference",
1306                                 "ses.calling_ss_user_reference",
1307                                 FT_BYTES, BASE_NONE,
1308                                 NULL,
1309                                 0x0,
1310                                 NULL,
1311                                 HFILL
1312                         }
1313                 },
1314                 {
1315                         &hf_common_reference,
1316                         {
1317                                 "Common Reference",
1318                                 "ses.common_reference",
1319                                 FT_BYTES, BASE_NONE,
1320                                 NULL,
1321                                 0x0,
1322                                 NULL,
1323                                 HFILL
1324                         }
1325                 },
1326                 {
1327                         &hf_additional_reference_information,
1328                         {
1329                                 "Additional Reference Information",
1330                                 "ses.additional_reference_information",
1331                                 FT_BYTES, BASE_NONE,
1332                                 NULL,
1333                                 0x0,
1334                                 NULL,
1335                                 HFILL
1336                         }
1337                 },
1338                 {
1339                         &hf_release_token,
1340                         {
1341                                 "release token",
1342                                 "ses.release_token",
1343                                 FT_BOOLEAN, 8,
1344                                 NULL,
1345                                 RELEASE_TOKEN,
1346                                 NULL,
1347                                 HFILL
1348                         }
1349                 },
1350                 {
1351                         &hf_major_activity_token,
1352                         {
1353                                 "major/activity token",
1354                                 "ses.major.token",
1355                                 FT_BOOLEAN, 8,
1356                                 NULL,
1357                                 MAJOR_ACTIVITY_TOKEN,
1358                                 NULL,
1359                                 HFILL
1360                         }
1361                 },
1362                 {
1363                         &hf_synchronize_minor_token,
1364                         {
1365                                 "synchronize minor token",
1366                                 "ses.synchronize_token",
1367                                 FT_BOOLEAN, 8,
1368                                 NULL,
1369                                 SYNCHRONIZE_MINOR_TOKEN,
1370                                 NULL,
1371                                 HFILL
1372                         }
1373                 },
1374                 {
1375                         &hf_data_token,
1376                         {
1377                                 "data token",
1378                                 "ses.data_token",
1379                                 FT_BOOLEAN, 8,
1380                                 NULL,
1381                                 DATA_TOKEN,
1382                                 "data  token",
1383                                 HFILL
1384                         }
1385                 },
1386                 {
1387                         &hf_able_to_receive_extended_concatenated_SPDU,
1388                         {
1389                                 "Able to receive extended concatenated SPDU",
1390                                 "ses.connect.f1",
1391                                 FT_BOOLEAN, 8,
1392                                 NULL,
1393                                 SES_EXT_CONT,
1394                                 NULL,
1395                                 HFILL
1396                         }
1397                 },
1398                 {
1399                         &hf_session_user_req_flags,
1400                         {
1401                                 "Flags",
1402                                 "ses.req.flags",
1403                                 FT_UINT16,
1404                                 BASE_HEX,
1405                                 NULL,
1406                                 0x0,
1407                                 NULL,
1408                                 HFILL
1409                         }
1410                 },
1411                 {
1412                         &hf_session_exception_report,
1413                         {
1414                                 "Session exception report",
1415                                 "ses.exception_report.",
1416                                 FT_BOOLEAN, 16,
1417                                 NULL,
1418                                 SES_EXCEPTION_REPORT,
1419                                 NULL,
1420                                 HFILL
1421                         }
1422                 },
1423                 {
1424                         &hf_data_separation_function_unit,
1425                         {
1426                                 "Data separation function unit",
1427                                 "ses.data_sep",
1428                                 FT_BOOLEAN, 16,
1429                                 NULL,
1430                                 DATA_SEPARATION_FUNCTION_UNIT,
1431                                 NULL,
1432                                 HFILL
1433                         }
1434                 },
1435                 {
1436                         &hf_symmetric_synchronize_function_unit,
1437                         {
1438                                 "Symmetric synchronize function unit",
1439                                 "ses.symm_sync",
1440                                 FT_BOOLEAN, 16,
1441                                 NULL,
1442                                 SYMMETRIC_SYNCHRONIZE_FUNCTION_UNIT,
1443                                 NULL,
1444                                 HFILL
1445                         }
1446                 },
1447                 {
1448                         &hf_typed_data_function_unit,
1449                         {
1450                                 "Typed data function unit",
1451                                 "ses.typed_data",
1452                                 FT_BOOLEAN, 16,
1453                                 NULL,
1454                                 TYPED_DATA_FUNCTION_UNIT,
1455                                 NULL,
1456                                 HFILL
1457                         }
1458                 },
1459                 {
1460                         &hf_exception_function_unit,
1461                         {
1462                                 "Exception function unit",
1463                                 "ses.exception_data",
1464                                 FT_BOOLEAN, 16,
1465                                 NULL,
1466                                 EXCEPTION_FUNCTION_UNIT,
1467                                 NULL,
1468                                 HFILL
1469                         }
1470                 },
1471                 {
1472                         &hf_capability_function_unit,
1473                         {
1474                                 "Capability function unit",
1475                                 "ses.capability_data",
1476                                 FT_BOOLEAN, 16,
1477                                 NULL,
1478                                 CAPABILITY_DATA_FUNCTION_UNIT,
1479                                 NULL,
1480                                 HFILL
1481                         }
1482                 },
1483                 {
1484                         &hf_negotiated_release_function_unit,
1485                         {
1486                                 "Negotiated release function unit",
1487                                 "ses.negotiated_release",
1488                                 FT_BOOLEAN, 16,
1489                                 NULL,
1490                                 NEGOTIATED_RELEASE_FUNCTION_UNIT,
1491                                 NULL,
1492                                 HFILL
1493                         }
1494                 },
1495                 {
1496                         &hf_activity_management_function_unit,
1497                         {
1498                                 "Activity management function unit",
1499                                 "ses.activity_management",
1500                                 FT_BOOLEAN, 16,
1501                                 NULL,
1502                                 ACTIVITY_MANAGEMENT_FUNCTION_UNIT,
1503                                 NULL,
1504                                 HFILL
1505                         }
1506                 },
1507                 {
1508                         &hf_resynchronize_function_unit,
1509                         {
1510                                 "Resynchronize function unit",
1511                                 "ses.resynchronize",
1512                                 FT_BOOLEAN, 16,
1513                                 NULL,
1514                                 RESYNCHRONIZE_FUNCTION_UNIT,
1515                                 NULL,
1516                                 HFILL
1517                         }
1518                 },
1519                 {
1520                         &hf_major_resynchronize_function_unit,
1521                         {
1522                                 "Major resynchronize function unit",
1523                                 "ses.major_resynchronize",
1524                                 FT_BOOLEAN, 16,
1525                                 NULL,
1526                                 MAJOR_SYNCHRONIZE_FUNCTION_UNIT,
1527                                 NULL,
1528                                 HFILL
1529                         }
1530                 },
1531                 {
1532                         &hf_minor_resynchronize_function_unit,
1533                         {
1534                                 "Minor resynchronize function unit",
1535                                 "ses.minor_resynchronize",
1536                                 FT_BOOLEAN, 16,
1537                                 NULL,
1538                                 MINOR_SYNCHRONIZE_FUNCTION_UNIT,
1539                                 NULL,
1540                                 HFILL
1541                         }
1542                 },
1543                 {
1544                         &hf_expedited_data_resynchronize_function_unit,
1545                         {
1546                                 "Expedited data function unit",
1547                                 "ses.expedited_data",
1548                                 FT_BOOLEAN, 16,
1549                                 NULL,
1550                                 EXPEDITED_DATA_FUNCTION_UNIT,
1551                                 NULL,
1552                                 HFILL
1553                         }
1554                 },
1555                 {
1556                         &hf_duplex_function_unit,
1557                         {
1558                                 "Duplex functional unit",
1559                                 "ses.duplex",
1560                                 FT_BOOLEAN, 16,
1561                                 NULL,
1562                                 DUPLEX_FUNCTION_UNIT,
1563                                 NULL,
1564                                 HFILL
1565                         }
1566                 },
1567                 {
1568                         &hf_half_duplex_function_unit,
1569                         {
1570                                 "Half-duplex functional unit",
1571                                 "ses.half_duplex",
1572                                 FT_BOOLEAN, 16,
1573                                 NULL,
1574                                 HALF_DUPLEX_FUNCTION_UNIT,
1575                                 NULL,
1576                                 HFILL
1577                         }
1578                 },
1579                 {
1580                         &hf_proposed_tsdu_maximum_size_i2r,
1581                         {
1582                                 "Proposed TSDU Maximum Size, Initiator to Responder",
1583                                 "ses.proposed_tsdu_maximum_size_i2r",
1584                                 FT_UINT16,
1585                                 BASE_DEC,
1586                                 NULL,
1587                                 0x0,
1588                                 NULL,
1589                                 HFILL
1590                         }
1591                 },
1592                 {
1593                         &hf_proposed_tsdu_maximum_size_r2i,
1594                         {
1595                                 "Proposed TSDU Maximum Size, Responder to Initiator",
1596                                 "ses.proposed_tsdu_maximum_size_r2i",
1597                                 FT_UINT16,
1598                                 BASE_DEC,
1599                                 NULL,
1600                                 0x0,
1601                                 NULL,
1602                                 HFILL
1603                         }
1604                 },
1605                 {
1606                         &hf_protocol_version_1,
1607                         {
1608                                 "Protocol Version 1",
1609                                 "ses.protocol_version1",
1610                                 FT_BOOLEAN, 8,
1611                                 NULL,
1612                                 PROTOCOL_VERSION_1,
1613                                 NULL,
1614                                 HFILL
1615                         }
1616                 },
1617                 {
1618                         &hf_protocol_version_2,
1619                         {
1620                                 "Protocol Version 2",
1621                                 "ses.protocol_version2",
1622                                 FT_BOOLEAN, 8,
1623                                 NULL,
1624                                 PROTOCOL_VERSION_2,
1625                                 NULL,
1626                                 HFILL
1627                         }
1628                 },
1629                 {
1630                         &hf_initial_serial_number,
1631                         {
1632                                 "Initial Serial Number",
1633                                 "ses.initial_serial_number",
1634                                 FT_STRING, BASE_NONE,
1635                                 NULL,
1636                                 0x0,
1637                                 NULL,
1638                                 HFILL
1639                         }
1640                 },
1641                 {
1642                         &hf_beginning_of_SSDU,
1643                         {
1644                                 "beginning of SSDU",
1645                                 "ses.begininng_of_SSDU",
1646                                 FT_BOOLEAN, 8,
1647                                 NULL,
1648                                 BEGINNING_SPDU,
1649                                 NULL,
1650                                 HFILL
1651                         }
1652                 },
1653                 {
1654                         &hf_end_of_SSDU,
1655                         {
1656                                 "end of SSDU",
1657                                 "ses.end_of_SSDU",
1658                                 FT_BOOLEAN, 8,
1659                                 NULL,
1660                                 END_SPDU,
1661                                 NULL,
1662                                 HFILL
1663                         }
1664                 },
1665                 {
1666                         &hf_release_token_setting,
1667                         {
1668                                 "release token setting",
1669                                 "ses.release_token_setting",
1670                                 FT_UINT8, BASE_HEX,
1671                                 VALS(token_setting_vals),
1672                                 0xC0,
1673                                 NULL,
1674                                 HFILL
1675                         }
1676                 },
1677                 {
1678                         &hf_major_activity_token_setting,
1679                         {
1680                                 "major/activity setting",
1681                                 "ses.major_activity_token_setting",
1682                                 FT_UINT8, BASE_HEX,
1683                                 VALS(token_setting_vals),
1684                                 0x30,
1685                                 "major/activity token setting",
1686                                 HFILL
1687                         }
1688                 },
1689                 {
1690                         &hf_synchronize_minor_token_setting,
1691                         {
1692                                 "synchronize-minor token setting",
1693                                 "ses.synchronize_minor_token_setting",
1694                                 FT_UINT8, BASE_HEX,
1695                                 VALS(token_setting_vals),
1696                                 0x0C,
1697                                 NULL,
1698                                 HFILL
1699                         }
1700                 },
1701                 {
1702                         &hf_data_token_setting,
1703                         {
1704                                 "data token setting",
1705                                 "ses.data_token_setting",
1706                                 FT_UINT8, BASE_HEX,
1707                                 VALS(token_setting_vals),
1708                                 0x03,
1709                                 NULL,
1710                                 HFILL
1711                         }
1712                 },
1713                 {
1714                         &hf_activity_identifier,
1715                         {
1716                                 "Activity Identifier",
1717                                 "ses.activity_identifier",
1718                                 FT_UINT32, BASE_DEC,
1719                                 NULL,
1720                                 0x0,
1721                                 NULL,
1722                                 HFILL
1723                         }
1724                 },
1725                 {
1726                         &hf_serial_number,
1727                         {
1728                                 "Serial Number",
1729                                 "ses.serial_number",
1730                                 FT_STRING, BASE_NONE,
1731                                 NULL,
1732                                 0x0,
1733                                 NULL,
1734                                 HFILL
1735                         }
1736                 },
1737                 {
1738                         &hf_calling_session_selector,
1739                         {
1740                                 "Calling Session Selector",
1741                                 "ses.calling_session_selector",
1742                                 FT_BYTES, BASE_NONE,
1743                                 NULL,
1744                                 0x0,
1745                                 NULL,
1746                                 HFILL
1747                         }
1748                 },
1749                 {
1750                         &hf_called_session_selector,
1751                         {
1752                                 "Called Session Selector",
1753                                 "ses.called_session_selector",
1754                                 FT_BYTES, BASE_NONE,
1755                                 NULL,
1756                                 0x0,
1757                                 NULL,
1758                                 HFILL
1759                         }
1760                 },
1761                 {
1762                         &hf_second_serial_number,
1763                         {
1764                                 "Second Serial Number",
1765                                 "ses.second_serial_number",
1766                                 FT_STRING, BASE_NONE,
1767                                 NULL,
1768                                 0x0,
1769                                 NULL,
1770                                 HFILL
1771                         }
1772                 },
1773                 {
1774                         &hf_second_initial_serial_number,
1775                         {
1776                                 "Second Initial Serial Number",
1777                                 "ses.second_initial_serial_number",
1778                                 FT_STRING, BASE_NONE,
1779                                 NULL,
1780                                 0x0,
1781                                 NULL,
1782                                 HFILL
1783                         }
1784                 },
1785                 {
1786                         &hf_large_initial_serial_number,
1787                         {
1788                                 "Large Initial Serial Number",
1789                                 "ses.large_initial_serial_number",
1790                                 FT_STRING, BASE_NONE,
1791                                 NULL,
1792                                 0x0,
1793                                 NULL,
1794                                 HFILL
1795                         }
1796                 },
1797                 {
1798                         &hf_large_second_initial_serial_number,
1799                         {
1800                                 "Large Second Initial Serial Number",
1801                                 "ses.large_second_initial_serial_number",
1802                                 FT_STRING, BASE_NONE,
1803                                 NULL,
1804                                 0x0,
1805                                 NULL,
1806                                 HFILL
1807                         }
1808                 },
1809                 {
1810                         &hf_connect_protocol_options_flags,
1811                         {
1812                                 "Flags",
1813                                 "ses.connect.flags",
1814                                 FT_UINT8,
1815                                 BASE_HEX,
1816                                 NULL,
1817                                 0x0,
1818                                 NULL,
1819                                 HFILL
1820                         }
1821                 },
1822                 {
1823                         &hf_version_number_options_flags,
1824
1825                         {
1826                                 "Flags",
1827                                 "ses.version.flags",
1828                                 FT_UINT8,
1829                                 BASE_HEX,
1830                                 NULL,
1831                                 0x0,
1832                                 NULL,
1833                                 HFILL
1834                         }
1835                 },
1836
1837                 {
1838                         &hf_token_item_options_flags,
1839
1840                         {
1841                                 "Flags",
1842                                 "ses.tken_item.flags",
1843                                 FT_UINT8,
1844                                 BASE_HEX,
1845                                 NULL,
1846                                 0x0,
1847                                 NULL,
1848                                 HFILL
1849                         }
1850                 },
1851
1852                 {
1853                         &hf_enclosure_item_options_flags,
1854
1855                         {
1856                                 "Flags",
1857                                 "ses.enclosure.flags",
1858                                 FT_UINT8,
1859                                 BASE_HEX,
1860                                 NULL,
1861                                 0x0,
1862                                 NULL,
1863                                 HFILL
1864                         }
1865                 },
1866
1867                 { &hf_ses_segment_data,
1868                   { "SES segment data", "ses.segment.data", FT_NONE, BASE_NONE,
1869                     NULL, 0x00, NULL, HFILL } },
1870                 { &hf_ses_segments,
1871                   { "SES segments", "ses.segments", FT_NONE, BASE_NONE,
1872                     NULL, 0x00, NULL, HFILL } },
1873                 { &hf_ses_segment,
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 } }
1902         };
1903
1904         static gint *ett[] =
1905         {
1906                 &ett_ses,
1907                 &ett_ses_param,
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,
1913                 &ett_ses_segment,
1914                 &ett_ses_segments
1915         };
1916         module_t *ses_module;
1917
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));
1921
1922         register_init_routine (&ses_reassemble_init);
1923
1924         ses_module = prefs_register_protocol(proto_ses, NULL);
1925
1926         prefs_register_bool_preference(ses_module, "desegment",
1927             "Reassemble session packets ",
1928             "Whether the session dissector should reassemble messages spanning multiple SES segments",
1929             &ses_desegment);
1930
1931         /*
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).
1936          */
1937         register_dissector("ses", dissect_ses, proto_ses);
1938 }
1939
1940 static gboolean
1941 dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1942 {
1943         /* must check that this really is a ses packet */
1944         int offset = 0;
1945         guint8 type;
1946         int len_len;
1947         guint16 len;
1948
1949         /* first, check do we have at least 4 bytes (type+length) */
1950         if (tvb_length(tvb) < 2)
1951                 return FALSE;   /* no */
1952
1953         /* can we recognize session PDU ? Return FALSE if  not */
1954         /*   get SPDU type */
1955         type = tvb_get_guint8(tvb, offset);
1956         /* check SPDU type */
1957         if (match_strval(type, ses_vals) == NULL)
1958         {
1959                 return FALSE;  /* no, it isn't a session PDU */
1960         }
1961
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) {
1965                 /*   get SPDU type */
1966                 type = tvb_get_guint8(tvb, offset+2);
1967                 /* check SPDU type */
1968                 if (match_strval(type, ses_vals) == NULL)
1969                 {
1970                         return FALSE;  /* no, it isn't a session PDU */
1971                 }
1972         }
1973
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 */
1982                 }
1983         }
1984
1985         /*  OK,let's check SPDU length  */
1986         /*  get length of SPDU */
1987         len = get_item_len(tvb, offset+1, &len_len);
1988
1989         /*  add header length     */
1990         len+=len_len;
1991         /* do we have enough bytes ? */
1992         if (tvb_length(tvb) < len)
1993                 return FALSE;   /* no */
1994
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 */
2001           }
2002         }
2003
2004         dissect_ses(tvb, pinfo, parent_tree);
2005         return TRUE;
2006 }
2007
2008 void
2009 proto_reg_handoff_ses(void)
2010 {
2011         /*   find data dissector  */
2012         data_handle = find_dissector("data");
2013
2014         /* define sub dissector */
2015         pres_handle = find_dissector("pres");
2016
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);
2021 }
2022
2023
2024
2025 void proto_register_clses(void)
2026 {
2027         proto_clses = proto_register_protocol(PROTO_STRING_CLSES, "CLSP", "clsp");
2028 }
2029
2030 void
2031 proto_reg_handoff_clses(void)
2032 {
2033         /* add our session dissector to cltp dissector list */
2034         heur_dissector_add("cltp", dissect_ses_heur, proto_clses);
2035 }
2036