Don't guard col_set_str (COL_PROTOCOL) with col_check
[metze/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 #include <epan/packet.h>
34
35 #include <stdio.h>
36 #include <string.h>
37
38 #include <epan/asn1.h>
39 #include "packet-ber.h"
40 #include "packet-ses.h"
41 #include "packet-frame.h"
42
43 /* #include <epan/prefs.h> */
44 #include <epan/emem.h>
45 #include <epan/strutil.h>
46
47 /* ses header fields             */
48 static int proto_ses          = -1;
49 static int hf_ses_type        = -1;
50 static int hf_ses_type_0      = -1;
51 static int hf_ses_length      = -1;
52 static int hf_ses_version     = -1;
53 static int hf_ses_reserved    = -1;
54
55 /* ses fields defining a sub tree */
56 static gint ett_ses           = -1;
57 static gint ett_ses_param     = -1;
58
59 /* 
60 ----------------------------------------------------------------------------------------------------------*/
61 static dissector_handle_t pres_handle = NULL;
62 /* 
63 ----------------------------------------------------------------------------------------------------------*/
64
65
66 /* flags */
67 static int hf_connect_protocol_options_flags = -1;
68 static int hf_version_number_options_flags = -1;
69 static int hf_enclosure_item_options_flags = -1;
70 static int hf_token_item_options_flags = -1;
71
72 static gint ett_connect_protocol_options_flags = -1;
73 static gint ett_protocol_version_flags = -1;
74 static gint ett_enclosure_item_flags = -1;
75 static gint ett_token_item_flags = -1;
76 static gint ett_ses_req_options_flags = -1;
77
78 /* called SS user reference */
79 static int hf_called_ss_user_reference = -1;
80
81 /* calling SS user reference */
82 static int hf_calling_ss_user_reference = -1;
83
84 /* common reference */
85 static int hf_common_reference = -1;
86
87 /* additional reference information */
88 static int hf_additional_reference_information = -1;
89
90 /* token item */
91 static int hf_release_token = -1;
92 static int hf_major_activity_token = -1;
93 static int hf_synchronize_minor_token = -1;
94 static int hf_data_token = -1;
95
96 /* protocol options */
97 static int hf_able_to_receive_extended_concatenated_SPDU = -1;
98
99 /* session requirement */
100 static int hf_session_user_req_flags = -1;
101 static int hf_session_exception_report= -1;
102 static int hf_data_separation_function_unit= -1;
103 static int hf_symmetric_synchronize_function_unit= -1;
104 static int hf_typed_data_function_unit= -1;
105 static int hf_exception_function_unit= -1;
106 static int hf_capability_function_unit=-1;
107 static int hf_negotiated_release_function_unit= -1;
108 static int hf_activity_management_function_unit= -1;
109 static int hf_resynchronize_function_unit= -1;
110 static int hf_major_resynchronize_function_unit= -1;
111 static int hf_minor_resynchronize_function_unit= -1;
112 static int hf_expedited_data_resynchronize_function_unit= -1;
113 static int hf_duplex_function_unit= -1;
114 static int hf_half_duplex_function_unit = -1;
115
116 /* TSDU maximum size */
117 static int hf_proposed_tsdu_maximum_size_i2r = -1;
118 static int hf_proposed_tsdu_maximum_size_r2i = -1;
119
120 /* protocol version */
121 static int hf_protocol_version_1 = -1;
122 static int hf_protocol_version_2 = -1;
123
124 /* initial serial number */
125 static int hf_initial_serial_number = -1;
126
127 /* enclosure item */
128 static int hf_beginning_of_SSDU = -1;
129 static int hf_end_of_SSDU = -1;
130
131 /* token setting item */
132
133 static const value_string token_setting_vals[] = {
134         { 0x00, "initiator's side" },
135         { 0x01, "responder's side" },
136         { 0x02, "called SS user's choice" },
137         { 0x03, "reserved" },
138         { 0, NULL }
139 };
140         
141 static int hf_release_token_setting = -1;
142 static int hf_major_activity_token_setting = -1;
143 static int hf_synchronize_minor_token_setting = -1;
144 static int hf_data_token_setting = -1;
145
146 /* calling session selector */
147 static int hf_calling_session_selector = -1;
148
149 /* called session selector */
150 static int hf_called_session_selector = -1;
151
152 /* activity id */
153 static int hf_activity_identifier = -1;
154
155 /* serial number */
156 static int hf_serial_number = -1;
157
158 /* second serial number */
159 static int hf_second_serial_number = -1;
160
161 /* second initial serial number */
162 static int hf_second_initial_serial_number = -1;
163
164 /* large initial serial number */
165 static int hf_large_initial_serial_number = -1;
166
167 /* large second initial serial number */
168 static int hf_large_second_initial_serial_number = -1;
169
170 const value_string ses_vals[] =
171 {
172   {SES_CONNECTION_REQUEST,                      "CONNECT (CN) SPDU" },                          /* 13 */
173   {SES_CONNECTION_ACCEPT,                       "ACCEPT (AC) SPDU" },                           /* 14 */
174   {SES_EXCEPTION_REPORT,                        "EXCEPTION REPORT (ER) SPDU"   },       /*  0 */
175   {SES_DATA_TRANSFER,                           "DATA TRANSFER (DT) SPDU" },            /*  1 */
176   {SES_PLEASE_TOKENS,                           "PLEASE TOKENS (PT) SPDU"   },          /*  2 */
177   {SES_EXPEDITED,                                       "EXPEDITED (EX) SPDU"   },                      /*  5 */
178   {SES_PREPARE,                                         "PREPARE (PR) SPDU"   },                        /*  7 */
179   {SES_NOT_FINISHED,                            "NOT FINISHED (NF) SPDU"   },           /*  8 */
180   {SES_FINISH,                                          "FINISH (FN) SPDU"   },                         /*  9 */
181   {SES_DISCONNECT,                                      "DISCONNECT (DN) SPDU"   },                     /* 10 */
182   {SES_REFUSE,                                          "REFUSE (RF) SPDU"   },                         /* 12 */
183   {SES_CONNECTION_DATA_OVERFLOW,        "CONNECT DATA OVERFLOW (CDO) SPDU"},/* 15 */
184   {SES_OVERFLOW_ACCEPT,                         "OVERFLOW ACCEPT (OA) SPDU"   },        /* 16 */
185   {SES_GIVE_TOKENS_CONFIRM,                     "GIVE TOKENS CONFIRM (GTC) SPDU"},      /* 21 */
186   {SES_GIVE_TOKENS_ACK,                         "GIVE TOKENS ACK (GTA) SPDU"   },       /* 22 */
187   {SES_ABORT,                                           "ABORT (AB) SPDU"   },                          /* 25 */
188   {SES_ABORT_ACCEPT,                            "ABORT ACCEPT (AA) SPDU"   },           /* 26 */
189   {SES_ACTIVITY_RESUME,                         "ACTIVITY RESUME (AR) SPDU"   },        /* 29 */
190   {SES_TYPED_DATA,                                      "TYPED DATA (TD) SPDU"   },                     /* 33 */
191   {SES_RESYNCHRONIZE_ACK,                       "RESYNCHRONIZE ACK (RA) SPDU"   },      /* 34 */
192   {SES_MAJOR_SYNC_POINT,                        "MAJOR SYNC POINT (MAP) SPDU"   },      /* 41 */
193   {SES_MAJOR_SYNC_ACK,                          "MAJOR SYNC ACK (MAA) SPDU"   },        /* 42 */
194   {SES_ACTIVITY_START,                          "ACTIVITY START (AS) SPDU"   },         /* 45 */
195   {SES_EXCEPTION_DATA,                          "EXCEPTION DATA (ED) SPDU"   },         /* 48 */
196   {SES_MINOR_SYNC_POINT,                        "MINOR SYNC POINT (MIP) SPDU"   },      /* 49 */
197   {SES_MINOR_SYNC_ACK,                          "MINOR SYNC ACK (MIA) SPDU"   },        /* 50 */
198   {SES_RESYNCHRONIZE,                           "RESYNCHRONIZE (RS) SPDU"   },          /* 53 */
199   {SES_ACTIVITY_DISCARD,                        "ACTIVITY DISCARD (AD) SPDU"   },       /* 57 */
200   {SES_ACTIVITY_DISCARD_ACK,            "ACTIVITY DISCARD ACK (ADA) SPDU" },/* 58 */
201   {SES_CAPABILITY,                                      "CAPABILITY DATA (CD) SPDU"   },        /* 61 */
202   {SES_CAPABILITY_DATA_ACK,                     "CAPABILITY DATA ACK (CDA) SPDU" }, /* 62 */
203   {0,             NULL           }
204 };
205
206 static const value_string ses_category0_vals[] =
207 {
208   {SES_PLEASE_TOKENS,    "Please tokens PDU"   },
209   {SES_GIVE_TOKENS,    "Give tokens PDU"   },
210   {0,             NULL           }
211 };
212
213
214 static const value_string param_vals[] =
215 {
216   {Connection_Identifier, "Connection Identifier"},
217   {Connect_Accept_Item, "Connect Accept Item"},
218   {Called_SS_user_Reference, "Called SS user Reference"},
219   {Calling_SS_user_Reference, "Calling SS user Reference"},
220   {Common_Reference, "Common Reference"},
221   {Sync_Type_Item, "Sync Type Item"},
222   {Token_Item, "Token Item"},
223   {Transport_Disconnect, "Transport_Disconnect"},
224   {Additional_Reference_Information, "Additional Reference Information"},
225   {Protocol_Options, "Protocol Options"},
226   {TSDU_Maximum_Size, "TSDU Maximum Size"},
227   {Version_Number, "Version Number"},
228   {Initial_Serial_Number, "Initial Serial Number"},
229   {Prepare_Type, "Prepare Type"},
230   {EnclosureItem, "Enclosure Item"},
231   {Token_Setting_Item, "Token Setting Item"},
232   {Resync_Type, "Resync Type"},
233   {Activity_Identifier, "Activity Identifier"},
234   {Serial_Number, "Serial Number"},
235   {Linking_Information, "Linking Information"},
236   {Reflect_Parameter, "Reflect Parameter"},
237   {Reason_Code, "Reason Code"},
238   {Calling_Session_Selector, "Calling Session Selector"},
239   {Called_Session_Selector, "Called Session Selector"},
240   {Second_Resync_Type, "Second Resync Type"},
241   {Second_Serial_Number, "Second Serial Number"},
242   {Second_Initial_Serial_Number, "Second Initial Serial Number"},
243   {Upper_Limit_Serial_Number, "Upper Limit Serial Number"},
244   {Large_Initial_Serial_Number, "Large Initial Serial Number"},
245   {Large_Second_Initial_Serial_Number, "Large Second Initial Serial Number"},
246   {Data_Overflow, "Data Overflow"},
247   {Session_Requirement, "Session Requirement"},
248   {User_Data, "Session user data"},
249   {Extended_User_Data, "Session extended user data"},
250   {0, NULL}
251 };
252
253 static const value_string reason_vals[] =
254 {
255   {reason_not_specified,  "Rejection by called SS-user; reason not specified" },
256   {temporary_congestion,    "Rejection by called SS-user due to temporary congestion"   },
257   {Subsequent,    "Rejection by called SS-user."   },
258   {Session_Selector_unknown,  "Session Selector unknown" },
259   {SS_user_not_attached_to_SSAP,    "SS-user not attached to SSAP"   },
260   {SPM_congestion_at_connect_time,    "SPM congestion at connect time"   },
261   {versions_not_supported,    "Proposed protocol versions not supported"   },
262   {SPM_reason_not_specified,    "Rejection by the SPM; reason not specified"   },
263   {SPM_implementation_restriction,    "Finish PDU"   },
264   {SES_DISCONNECT,    "Rejection by the SPM; implementation restriction stated in the PICS"   },
265   {0,             NULL           }
266 };
267
268 /* desegmentation of OSI over ses  */
269 /*static gboolean ses_desegment = TRUE;*/
270
271 /* RTSE reassembly data */
272 static guint ses_pres_ctx_id = 0;
273 static gboolean ses_rtse_reassemble = FALSE;
274
275 /* find the dissector for data */
276 static dissector_handle_t data_handle;
277
278 static void
279 call_pres_dissector(tvbuff_t *tvb, int offset, guint16 param_len,
280     packet_info *pinfo, proto_tree *tree, proto_tree *param_tree,
281     struct SESSION_DATA_STRUCTURE *session)
282 {
283         void *saved_private_data;
284
285         /* do we have OSI presentation packet dissector ? */
286         if(!pres_handle)
287         {
288                 /* No - display as data */
289                 if (tree)
290                 {
291                         proto_tree_add_text(param_tree, tvb, offset, param_len,
292                             "User data");
293                 }
294         }
295         else
296         {
297                 /* Yes - call presentation dissector */
298                 tvbuff_t *next_tvb;
299
300                 next_tvb = tvb_new_subset(tvb, offset, param_len, param_len);
301                 TRY
302                 {
303                         /*   save type of session pdu. We'll need it in the presentation dissector  */
304                         saved_private_data = pinfo->private_data;
305                         pinfo->private_data = session;
306                         call_dissector(pres_handle, next_tvb, pinfo, tree);
307                         pinfo->private_data = saved_private_data;
308                 }
309                 CATCH_ALL
310                 {
311                         show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
312                 }
313                 ENDTRY;
314         }
315 }
316
317 /* this routine returns length of parameter field, parameter group,
318    or parameter */
319 static int
320 get_item_len(tvbuff_t *tvb, int offset, int *len_len)
321 {
322         guint16 len;
323
324         len = tvb_get_guint8(tvb, offset);
325         if(len == TWO_BYTE_LEN)
326         {
327                 len = tvb_get_ntohs(tvb, offset+1);
328                 *len_len = 3;
329         }
330         else
331                 *len_len = 1;
332         return len;
333 }
334
335 static gboolean
336 dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree,
337     proto_tree *param_tree, packet_info *pinfo, guint8 param_type,
338     guint16 param_len, struct SESSION_DATA_STRUCTURE *session)
339 {
340         gboolean has_user_information = TRUE;
341         guint16       flags;
342         proto_item   *tf;
343         proto_tree   *flags_tree;
344         asn1_ctx_t asn1_ctx;
345         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
346
347         switch (param_type)
348         {
349         case Called_SS_user_Reference:
350                 if (param_len == 0)
351                         break;
352                 if (tree)
353                 {
354                         proto_tree_add_item(param_tree,
355                             hf_called_ss_user_reference,
356                             tvb, offset, param_len, FALSE);
357                 }
358                 break;
359
360         case Calling_SS_user_Reference:
361                 if (param_len == 0)
362                         break;
363                 if (tree)
364                 {
365                         proto_tree_add_item(param_tree,
366                             hf_calling_ss_user_reference,
367                             tvb, offset, param_len, FALSE);
368                 }
369                 break;
370
371         case Common_Reference:
372                 if (param_len == 0)
373                         break;
374                 if (tree)
375                 {
376                         proto_tree_add_item(param_tree,
377                             hf_common_reference,
378                             tvb, offset, param_len, FALSE);
379                 }
380                 break;
381
382         case Additional_Reference_Information:
383                 if (param_len == 0)
384                         break;
385                 if (tree)
386                 {
387                         proto_tree_add_item(param_tree,
388                             hf_additional_reference_information,
389                             tvb, offset, param_len, FALSE);
390                 }
391                 break;
392
393         case Token_Item:
394                 if (param_len != 1)
395                 {
396                         proto_tree_add_text(param_tree, tvb, offset,
397                             param_len, "Length is %u, should be 1",
398                             param_len);
399                         break;
400                 }
401                 if (tree)
402                 {
403                         flags = tvb_get_guint8(tvb, offset);
404                         tf = proto_tree_add_uint(param_tree,
405                             hf_token_item_options_flags, tvb, offset, 1,
406                             flags);
407                         flags_tree = proto_item_add_subtree(tf,
408                             ett_token_item_flags);
409                         proto_tree_add_boolean(flags_tree, hf_release_token,
410                             tvb, offset, 1, flags);
411                         proto_tree_add_boolean(flags_tree,
412                             hf_major_activity_token, tvb, offset, 1, flags);
413                         proto_tree_add_boolean(flags_tree,
414                             hf_synchronize_minor_token, tvb, offset, 1, flags);
415                         proto_tree_add_boolean(flags_tree, hf_data_token, tvb,
416                             offset, 1, flags);
417                 }
418                 break;
419
420         case Transport_Disconnect:
421                 if (param_len != 1)
422                 {
423                         proto_tree_add_text(param_tree, tvb, offset,
424                             param_len, "Length is %u, should be 1",
425                             param_len);
426                         break;
427                 }
428                 if (tree)
429                 {
430                         guint8       flags;
431
432                         flags = tvb_get_guint8(tvb, offset);
433                         if(flags & transport_connection_is_released )
434                         {
435                                 proto_tree_add_text(param_tree, tvb, offset, 1,
436                                     "transport connection is released");
437                         }
438                         else
439                         {
440                                 proto_tree_add_text(param_tree, tvb, offset, 1,
441                                     "transport connection is kept");
442                         }
443
444                         if(flags & user_abort )
445                         {
446                                 proto_tree_add_text(param_tree, tvb, offset, 1,
447                                     "user abort");
448                                 session->abort_type = SESSION_USER_ABORT;
449                         }
450                         else
451                         {
452                                 session->abort_type = SESSION_PROVIDER_ABORT;
453                         }
454
455                         if(flags & protocol_error )
456                         {
457                                 proto_tree_add_text(param_tree, tvb, offset, 1,
458                                     "protocol error");
459                         }
460
461                         if(flags & no_reason )
462                         {
463                                 proto_tree_add_text(param_tree, tvb, offset, 1,
464                                     "no reason");
465                         }
466
467                         if(flags & implementation_restriction )
468                         {
469                                 proto_tree_add_text(param_tree, tvb, offset, 1,
470                                     "implementation restriction");
471                         }
472                 }
473                 break;
474
475         case Protocol_Options:
476                 if (param_len != 1)
477                 {
478                         proto_tree_add_text(param_tree, tvb, offset,
479                             param_len, "Length is %u, should be 1",
480                             param_len);
481                         break;
482                 }
483                 if (tree)
484                 {
485                         flags = tvb_get_guint8(tvb, offset);
486                         tf = proto_tree_add_uint(param_tree,
487                             hf_connect_protocol_options_flags, tvb, offset, 1,
488                             flags);
489                         flags_tree = proto_item_add_subtree(tf, 
490                             ett_connect_protocol_options_flags);
491                         proto_tree_add_boolean(flags_tree, 
492                             hf_able_to_receive_extended_concatenated_SPDU,
493                             tvb, offset, 1, flags);
494                 }
495                 break;
496
497         case Session_Requirement:
498                 if (param_len != 2)
499                 {
500                         proto_tree_add_text(param_tree, tvb, offset,
501                             param_len, "Length is %u, should be 2",
502                             param_len);
503                         break;
504                 }
505                 if (tree)
506                 {
507                         flags = tvb_get_ntohs(tvb, offset);
508                         tf = proto_tree_add_uint(param_tree,
509                             hf_session_user_req_flags, tvb, offset, 2,
510                             flags);
511                         flags_tree = proto_item_add_subtree(tf,
512                             ett_ses_req_options_flags);
513                         proto_tree_add_boolean(flags_tree,
514                             hf_session_exception_report, tvb, offset, 2, flags);
515                         proto_tree_add_boolean(flags_tree,
516                             hf_data_separation_function_unit, tvb, offset, 2,
517                             flags);
518                         proto_tree_add_boolean(flags_tree,
519                             hf_symmetric_synchronize_function_unit, 
520                             tvb, offset, 2, flags);
521                         proto_tree_add_boolean(flags_tree,
522                             hf_typed_data_function_unit, tvb, offset, 2, flags);
523                         proto_tree_add_boolean(flags_tree,
524                             hf_exception_function_unit, tvb, offset, 2, flags);
525                         proto_tree_add_boolean(flags_tree,
526                             hf_capability_function_unit, tvb, offset, 2, flags);
527                         proto_tree_add_boolean(flags_tree,
528                             hf_negotiated_release_function_unit, 
529                             tvb, offset, 2, flags);
530                         proto_tree_add_boolean(flags_tree,
531                             hf_activity_management_function_unit, 
532                             tvb, offset, 2, flags);
533                         proto_tree_add_boolean(flags_tree,
534                             hf_resynchronize_function_unit, tvb, offset, 2,
535                             flags);
536                         proto_tree_add_boolean(flags_tree,
537                             hf_major_resynchronize_function_unit, 
538                             tvb, offset, 2, flags);
539                         proto_tree_add_boolean(flags_tree,
540                             hf_minor_resynchronize_function_unit, 
541                             tvb, offset, 2, flags);
542                         proto_tree_add_boolean(flags_tree, 
543                             hf_expedited_data_resynchronize_function_unit,
544                             tvb, offset, 2, flags);
545                         proto_tree_add_boolean(flags_tree,
546                             hf_duplex_function_unit, tvb, offset, 2, flags);
547                         proto_tree_add_boolean(flags_tree,
548                             hf_half_duplex_function_unit,
549                             tvb, offset, 2, flags);
550                 }
551                 break;
552
553         case TSDU_Maximum_Size:
554                 if (param_len != 4)
555                 {
556                         proto_tree_add_text(param_tree, tvb, offset,
557                             param_len, "Length is %u, should be 4",
558                             param_len);
559                         break;
560                 }
561                 if (tree)
562                 {
563                         proto_tree_add_item(param_tree,
564                             hf_proposed_tsdu_maximum_size_i2r,
565                             tvb, offset, 2, FALSE);
566                         proto_tree_add_item(param_tree,
567                             hf_proposed_tsdu_maximum_size_r2i,
568                             tvb, offset+2, 2, FALSE);
569                 }
570                 break;
571
572         case Version_Number:
573                 if (param_len != 1)
574                 {
575                         proto_tree_add_text(param_tree, tvb, offset,
576                             param_len, "Length is %u, should be 1",
577                             param_len);
578                         break;
579                 }
580                 if (tree)
581                 {
582                         flags = tvb_get_guint8(tvb, offset);
583                         tf = proto_tree_add_uint(param_tree,
584                             hf_version_number_options_flags, tvb, offset, 1,
585                             flags);
586                         flags_tree = proto_item_add_subtree(tf,
587                             ett_protocol_version_flags);
588                         proto_tree_add_boolean(flags_tree,
589                             hf_protocol_version_2, tvb, offset, 1, flags);
590                         proto_tree_add_boolean(flags_tree,
591                             hf_protocol_version_1, tvb, offset, 1, flags);
592                 }
593                 break;
594
595         case Initial_Serial_Number:
596                 if (param_len == 0)
597                         break;
598                 if (tree)
599                 {
600                         proto_tree_add_item(param_tree,
601                             hf_initial_serial_number,
602                             tvb, offset, param_len, FALSE);
603                 }
604                 break;
605
606         case EnclosureItem:
607                 if (param_len != 1)
608                 {
609                         proto_tree_add_text(param_tree, tvb, offset,
610                             param_len, "Length is %u, should be 1",
611                             param_len);
612                         break;
613                 }
614                 flags = tvb_get_guint8(tvb, offset);
615                 if (tree)
616                 {
617                         tf = proto_tree_add_uint(param_tree,
618                             hf_enclosure_item_options_flags, tvb, offset, 1,
619                             flags);
620                         flags_tree = proto_item_add_subtree(tf,
621                             ett_enclosure_item_flags);
622                         proto_tree_add_boolean(flags_tree, hf_end_of_SSDU,
623                             tvb, offset, 1, flags);
624                         proto_tree_add_boolean(flags_tree, hf_beginning_of_SSDU,
625                             tvb, offset, 1, flags);
626                 }
627                 if (flags & END_SPDU) {
628                         /*
629                          * In Data Transfer and Typed Data SPDUs, (X.225: 8.3.{11,13}.4)
630                          * "The User Information Field shall be present
631                          * if the Enclosure Item is not present, or has
632                          * bit 2 = 0", which presumably means it shall
633                          * *not* be present if the Enclosure item *is*
634                          * present and has bit 2 = 1.
635                          */
636
637                   if(!(flags & BEGINNING_SPDU)) {
638                     /* X.225 7.11.2 also states:
639                      * "All DATA TRANSFER SPDUs, except the last DATA TRANSFER SPDU in a sequence greater than one, must have user information"
640                      * So if BEGINNING_SPDU and END_SPDU are set in the enclosure item, then this is presumably a sequence of one and 
641                      * consequently there must be user information.
642                      *
643                      * So, there is only no user information if *only* END_SPDU is set.
644                      */
645
646                      has_user_information = FALSE;
647                   }
648                 }
649                 break;
650
651         case Token_Setting_Item:
652                 if (param_len != 1)
653                 {
654                         proto_tree_add_text(param_tree, tvb, offset,
655                             param_len, "Length is %u, should be 1",
656                             param_len);
657                         break;
658                 }
659                 if (tree)
660                 {
661                         proto_tree_add_item(param_tree,
662                             hf_release_token_setting,
663                             tvb, offset, 1, FALSE);
664                         proto_tree_add_item(param_tree,
665                             hf_major_activity_token_setting,
666                             tvb, offset, 1, FALSE);
667                         proto_tree_add_item(param_tree,
668                             hf_synchronize_minor_token_setting,
669                             tvb, offset, 1, FALSE);
670                         proto_tree_add_item(param_tree,
671                             hf_data_token_setting,
672                             tvb, offset, 1, FALSE);
673                 }
674                 break;
675
676         case Activity_Identifier:
677                 if (param_len == 0)
678                         break;
679                 if (tree)
680                 {
681                         dissect_ber_integer(FALSE, &asn1_ctx, param_tree, tvb, offset,
682                             hf_activity_identifier, NULL);
683                 }
684                 break;
685
686         case Serial_Number:
687                 if (param_len == 0)
688                         break;
689                 if (tree)
690                 {
691                         proto_tree_add_item(param_tree,
692                             hf_serial_number,
693                             tvb, offset, param_len, FALSE);
694                 }
695                 break;
696
697         case Reason_Code:
698 /*
699         0:      Rejection by called SS-user; reason not specified.
700         1:      Rejection by called SS-user due to temporary congestion.
701         2:      Rejection by called SS-user. Subsequent octets may be used for user data 
702 up to a length of 512 octets if Protocol Version 1 has been selected, and up 
703 to a length such that the total length (including SI and LI)  of the SPDU 
704 does not exceed 65 539 octets if Protocol Version 2 has been selected.
705         128 + 1:        Session Selector unknown.
706         128 + 2:        SS-user not attached to SSAP.
707         128 + 3:        SPM congestion at connect time.
708         128 + 4:        Proposed protocol versions not supported.
709         128 + 5:        Rejection by the SPM; reason not specified.
710         128 + 6:        Rejection by the SPM; implementation restriction stated in the 
711 PICS.    */
712                 if (param_len < 1)
713                 {
714                         proto_tree_add_text(param_tree, tvb, offset,
715                             param_len, "Length is %u, should be >= 1",
716                             param_len);
717                         break;
718                 }
719                 if (tree)
720                 {
721                         guint8      reason_code;
722
723                         reason_code = tvb_get_guint8(tvb, offset);
724                         proto_tree_add_text(param_tree, tvb, offset, 1,
725                             "Reason Code: %s",
726                             val_to_str(reason_code, reason_vals, "Unknown (%u)"));
727                 }
728                 offset++;
729                 param_len--;
730                 if (param_len != 0)
731                 {
732                         call_pres_dissector(tvb, offset, param_len,
733                             pinfo, tree, param_tree, session);
734                 }
735                 break;
736
737         case Calling_Session_Selector:
738                 if (param_len == 0)
739                         break;
740                 if (tree)
741                 {
742                         proto_tree_add_item(param_tree,
743                             hf_calling_session_selector,
744                             tvb, offset, param_len, FALSE);
745                 }
746                 break;
747
748         case Called_Session_Selector:
749                 if (param_len == 0)
750                         break;
751                 if (tree)
752                 {
753                         proto_tree_add_item(param_tree,
754                             hf_called_session_selector,
755                             tvb, offset, param_len, FALSE);
756                 }
757                 break;
758
759         case Second_Serial_Number:
760                 if (param_len == 0)
761                         break;
762                 if (tree)
763                 {
764                         proto_tree_add_item(param_tree,
765                             hf_second_serial_number,
766                             tvb, offset, param_len, FALSE);
767                 }
768                 break;
769
770         case Second_Initial_Serial_Number:
771                 if (param_len == 0)
772                         break;
773                 if (tree)
774                 {
775                         proto_tree_add_item(param_tree,
776                             hf_second_initial_serial_number,
777                             tvb, offset, param_len, FALSE);
778                 }
779                 break;
780
781         case Large_Initial_Serial_Number:
782                 if (param_len == 0)
783                         break;
784                 if (tree)
785                 {
786                         proto_tree_add_item(param_tree,
787                             hf_large_initial_serial_number,
788                             tvb, offset, param_len, FALSE);
789                 }
790                 break;
791
792         case Large_Second_Initial_Serial_Number:
793                 if (param_len == 0)
794                         break;
795                 if (tree)
796                 {
797                         proto_tree_add_item(param_tree,
798                             hf_large_second_initial_serial_number,
799                             tvb, offset, param_len, FALSE);
800                 }
801                 break;
802
803         default:
804                 break;
805         }
806         return has_user_information;
807 }
808
809 static gboolean
810 dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree,
811     proto_tree *pg_tree, packet_info *pinfo, guint16 pg_len,
812     struct SESSION_DATA_STRUCTURE *session)
813 {
814         gboolean has_user_information = TRUE;
815         proto_item *ti;
816         proto_tree *param_tree;
817         guint8 param_type;
818         const char *param_str;
819         int len_len;
820         guint16 param_len;
821
822         while(pg_len != 0)
823         {
824                 param_type = tvb_get_guint8(tvb, offset);
825                 ti = proto_tree_add_text(pg_tree, tvb, offset, -1, "%s",
826                     val_to_str(param_type, param_vals,
827                       "Unknown parameter type (0x%02x)"));
828                 param_tree = proto_item_add_subtree(ti, ett_ses_param);
829                 param_str = match_strval(param_type, param_vals);
830                 proto_tree_add_text(param_tree, tvb, offset, 1,
831                     "Parameter type: %s",
832                     param_str != NULL ? param_str : "Unknown");
833                 offset++;
834                 pg_len--;
835                 param_len = get_item_len(tvb, offset, &len_len);
836                 if (len_len > pg_len) {
837                         proto_item_set_len(ti, pg_len + 1);
838                         proto_tree_add_text(param_tree, tvb, offset, pg_len,
839                             "Parameter length doesn't fit in parameter");
840                         return has_user_information;
841                 }
842                 pg_len -= len_len;
843                 if (param_len > pg_len) {
844                         proto_item_set_len(ti, pg_len + 1 + len_len);
845                         proto_tree_add_text(param_tree, tvb, offset, pg_len,
846                             "Parameter length: %u, should be <= %u",
847                             param_len, pg_len);
848                         return has_user_information;
849                 }
850                 proto_item_set_len(ti, 1 + len_len + param_len);
851                 proto_tree_add_text(param_tree, tvb, offset, len_len,
852                     "Parameter length: %u", param_len);
853                 offset += len_len;
854                     
855                 if (param_str != NULL)
856                 {
857                         switch(param_type)
858                         {
859                         /* PG's in PG's are invalid, presumably */
860                         case Extended_User_Data:
861                         case User_Data:
862                         case Connect_Accept_Item:
863                         case Connection_Identifier:
864                         case Linking_Information:
865                                 proto_tree_add_text(param_tree, tvb, offset,
866                                     param_len,
867                                     "Parameter group inside parameter group");
868                                 break;
869
870                         default:
871                                 if (!dissect_parameter(tvb, offset, tree,
872                                     param_tree, pinfo, param_type, param_len,
873                                     session))
874                                         has_user_information = FALSE;
875                                 break;
876                         }
877                 }
878                 offset += param_len;
879                 pg_len -= param_len;
880         }
881         return has_user_information;
882 }
883
884 /*
885  * Returns TRUE if there's a User Information field in this SPDU, FALSE
886  * otherwise.
887  */
888 static gboolean
889 dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree,
890     proto_tree *ses_tree, packet_info *pinfo,
891     struct SESSION_DATA_STRUCTURE *session)
892 {
893         gboolean has_user_information = TRUE;
894         proto_item *ti;
895         proto_tree *param_tree;
896         guint8 param_type;
897         const char *param_str;
898         int len_len;
899         guint16 param_len;
900
901         while(len != 0)
902         {
903                 param_type = tvb_get_guint8(tvb, offset);
904                 ti = proto_tree_add_text(ses_tree, tvb, offset, -1, "%s",
905                     val_to_str(param_type, param_vals,
906                       "Unknown parameter type (0x%02x)"));
907                 param_tree = proto_item_add_subtree(ti, ett_ses_param);
908                 param_str = match_strval(param_type, param_vals);
909                 proto_tree_add_text(param_tree, tvb, offset, 1,
910                     "Parameter type: %s",
911                     param_str != NULL ? param_str : "Unknown");
912                 offset++;
913                 len--;
914                 param_len = get_item_len(tvb, offset, &len_len);
915                 if (len_len > len) {
916                         proto_item_set_len(ti, len + 1 );
917                         proto_tree_add_text(param_tree, tvb, offset, len,
918                             "Parameter length doesn't fit in parameter");
919                         return has_user_information;
920                 }
921                 len -= len_len;
922                 if (param_len > len) {
923                         proto_item_set_len(ti, len + 1 + len_len);
924                         proto_tree_add_text(param_tree, tvb, offset, len,
925                             "Parameter length: %u, should be <= %u",
926                             param_len, len);
927                         return has_user_information;
928                 }
929                 proto_item_set_len(ti, 1 + len_len + param_len);
930                 proto_tree_add_text(param_tree, tvb, offset, len_len,
931                     "Parameter length: %u", param_len);
932                 offset += len_len;
933                     
934                 if (param_str != NULL)
935                 {
936                         switch(param_type)
937                         {
938                         case Extended_User_Data:
939                                 call_pres_dissector(tvb, offset, param_len,
940                                     pinfo, tree, param_tree, session);
941                                 break;
942
943                         case User_Data:
944                                 call_pres_dissector(tvb, offset, param_len,
945                                     pinfo, tree, param_tree, session);
946                                 break;
947
948                         /* handle PGI's  */
949                         case Connect_Accept_Item:
950                         case Connection_Identifier:
951                         case Linking_Information:
952                                 /* Yes. */
953                                 if (!dissect_parameter_group(tvb, offset, tree,
954                                     param_tree, pinfo, param_len, session))
955                                         has_user_information = FALSE;
956                                 break;
957
958                         /* everything else is a PI */
959                         default:
960                                 if (!dissect_parameter(tvb, offset, tree,
961                                     param_tree, pinfo, param_type, param_len,
962                                     session))
963                                         has_user_information = FALSE;
964                                 break;
965                         }
966                 }
967                 offset += param_len;
968                 len -= param_len;
969         }
970         return has_user_information;
971 }
972
973 /*
974  * Dissect an SPDU.
975  */
976 static int
977 dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
978     gboolean tokens)
979 {
980         gboolean has_user_information = FALSE;
981         guint8 type;
982         proto_item *ti = NULL;
983         proto_tree *ses_tree = NULL;
984         int len_len;
985         guint16 parameters_len;
986         tvbuff_t *next_tvb;
987         void *save_private_data;
988         guint32 *pres_ctx_id = NULL;
989         struct SESSION_DATA_STRUCTURE session;
990
991         /*
992          * Get SPDU type.
993          */
994         type = tvb_get_guint8(tvb, offset);
995         session.spdu_type = type;
996         session.abort_type = SESSION_NO_ABORT;
997         session.ros_op = 0;
998         session.rtse_reassemble = FALSE;
999
1000         if (tokens) {
1001                 if (check_col(pinfo->cinfo, COL_INFO))
1002                         col_add_str(pinfo->cinfo, COL_INFO,
1003                             val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)"));
1004                 if (tree) {
1005                         ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
1006                             -1, FALSE);
1007                         ses_tree = proto_item_add_subtree(ti, ett_ses);
1008                         proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb,
1009                             offset, 1, type);
1010                 }
1011         } else {
1012                 if (check_col(pinfo->cinfo, COL_INFO))
1013                         col_add_str(pinfo->cinfo, COL_INFO,
1014                             val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
1015                 if (tree) {
1016                         ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
1017                             -1, FALSE);
1018                         ses_tree = proto_item_add_subtree(ti, ett_ses);
1019                         proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
1020                             offset, 1, type);
1021                 }
1022
1023                 /*
1024                  * Might this SPDU have a User Information field?
1025                  */
1026                 switch (type) {
1027
1028                 case SES_DATA_TRANSFER:
1029                 case SES_EXPEDITED:
1030                 case SES_TYPED_DATA:
1031                         has_user_information = TRUE;
1032                         break;
1033                 case SES_MAJOR_SYNC_POINT:
1034                         pres_ctx_id = p_get_proto_data (pinfo->fd, proto_ses);
1035                         if (ses_rtse_reassemble != 0 && !pres_ctx_id) {
1036                                 /* First time visited - save pres_ctx_id */
1037                                 pres_ctx_id = se_alloc (sizeof (guint32));
1038                                 *pres_ctx_id = ses_pres_ctx_id;
1039                                 p_add_proto_data (pinfo->fd, proto_ses, pres_ctx_id);
1040                         }
1041                         if (pres_ctx_id) {
1042                                 session.pres_ctx_id = *pres_ctx_id;
1043                                 session.rtse_reassemble = TRUE;
1044                                 has_user_information = TRUE;
1045                         }
1046                         ses_rtse_reassemble = FALSE;
1047                         break;
1048                 }
1049         }
1050         offset++;
1051
1052         /* get length of SPDU parameter field */
1053         parameters_len = get_item_len(tvb, offset, &len_len);
1054         if (tree)
1055                 proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset,
1056                     len_len, parameters_len);
1057         offset += len_len;
1058
1059         /* Dissect parameters. */
1060         if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree,
1061             pinfo, &session))
1062                 has_user_information = FALSE;
1063         offset += parameters_len;
1064         
1065         proto_item_set_end(ti, tvb, offset);
1066
1067         /* Dissect user information, if present */
1068         if (has_user_information) {
1069                 if (tvb_reported_length_remaining(tvb, offset) > 0 || type == SES_MAJOR_SYNC_POINT) {
1070                         next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1071
1072                         /* do we have OSI presentation packet dissector ? */
1073                         if(!pres_handle)
1074                         {
1075                                 call_dissector(data_handle, next_tvb, pinfo,
1076                                     tree);
1077                         }
1078                         else
1079                         {
1080                                 /*   save type of session pdu. We'll need it in the presentation dissector  */
1081                                 save_private_data = pinfo->private_data;
1082                                 pinfo->private_data = &session;
1083                                 call_dissector(pres_handle, next_tvb, pinfo,
1084                                     tree);
1085                                 pinfo->private_data = save_private_data;
1086                         }
1087
1088                         /*
1089                          * No more SPDUs to dissect.  Set the offset to the
1090                          * end of the tvbuff.
1091                          */
1092                         offset = tvb_length(tvb);
1093                         if (session.rtse_reassemble && type == SES_DATA_TRANSFER) {
1094                                 ses_pres_ctx_id = session.pres_ctx_id;
1095                                 ses_rtse_reassemble = TRUE;
1096                         }
1097                 }
1098         }
1099         return offset;
1100 }
1101
1102 /*
1103  * Dissect SPDUs inside a TSDU.
1104  */
1105 static void
1106 dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1107 {
1108         int offset = 0;
1109         guint8 type;
1110
1111         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SES");
1112         if (check_col(pinfo->cinfo, COL_INFO))
1113                 col_clear(pinfo->cinfo, COL_INFO);
1114
1115         /*
1116          * Do we have a category 0 SPDU (GIVE_TOKENS/PLEASE_TOKENS) as
1117          * the first SPDU?
1118          *
1119          * If so, dissect it as such (GIVE_TOKENS and DATA_TRANSFER have
1120          * the same SPDU type value).
1121          */
1122         type = tvb_get_guint8(tvb, offset);
1123         if (type == SES_PLEASE_TOKENS || type == SES_GIVE_TOKENS)
1124                 offset = dissect_spdu(tvb, offset, pinfo, tree, TOKENS_SPDU);
1125
1126         /* Dissect the remaining SPDUs. */
1127         while (tvb_reported_length_remaining(tvb, offset) > 0)
1128                 offset = dissect_spdu(tvb, offset, pinfo, tree, NON_TOKENS_SPDU);
1129 }
1130
1131 void
1132 proto_register_ses(void)
1133 {
1134         static hf_register_info hf[] =
1135         {
1136                 {
1137                         &hf_ses_type,
1138                         {
1139                                 "SPDU Type",
1140                                 "ses.type",
1141                                 FT_UINT8,
1142                                 BASE_DEC,
1143                                 VALS(ses_vals),
1144                                 0x0,
1145                                 NULL, HFILL
1146                         }
1147                 },
1148                 {
1149                         &hf_ses_type_0,
1150                         {
1151                                 "SPDU Type",
1152                                 "ses.type",
1153                                 FT_UINT8,
1154                                 BASE_DEC,
1155                                 VALS(ses_category0_vals),
1156                                 0x0,
1157                                 NULL, HFILL
1158                         }
1159                 },
1160                 {
1161                         &hf_ses_length,
1162                         {
1163                                 "Length",
1164                                 "ses.length",
1165                                 FT_UINT16,
1166                                 BASE_DEC,
1167                                 NULL,
1168                                 0x0,
1169                                 NULL, HFILL
1170                         }
1171                 },
1172
1173                 {
1174                         &hf_ses_version,
1175                         {
1176                                 "Version",
1177                                 "ses.version",
1178                                 FT_UINT8,
1179                                 BASE_DEC,
1180                                 NULL,
1181                                 0x0,
1182                                 NULL, HFILL
1183                         }
1184                 },
1185                 {
1186                         &hf_ses_reserved,
1187                         {
1188                                 "Reserved",
1189                                 "ses.reserved",
1190                                 FT_UINT8,
1191                                 BASE_DEC,
1192                                 NULL,
1193                                 0x0,
1194                                 NULL, HFILL
1195                         }
1196                 },
1197                 {
1198                         &hf_called_ss_user_reference,
1199                         {
1200                                 "Called SS User Reference",
1201                                 "ses.called_ss_user_reference",
1202                                 FT_BYTES, BASE_NONE,
1203                                 NULL,
1204                                 0x0,
1205                                 NULL,
1206                                 HFILL
1207                         }
1208                 },
1209                 {
1210                         &hf_calling_ss_user_reference,
1211                         {
1212                                 "Calling SS User Reference",
1213                                 "ses.calling_ss_user_reference",
1214                                 FT_BYTES, BASE_NONE,
1215                                 NULL,
1216                                 0x0,
1217                                 NULL,
1218                                 HFILL
1219                         }
1220                 },
1221                 {
1222                         &hf_common_reference,
1223                         {
1224                                 "Common Reference",
1225                                 "ses.common_reference",
1226                                 FT_BYTES, BASE_NONE,
1227                                 NULL,
1228                                 0x0,
1229                                 NULL,
1230                                 HFILL
1231                         }
1232                 },
1233                 {
1234                         &hf_additional_reference_information,
1235                         {
1236                                 "Additional Reference Information",
1237                                 "ses.additional_reference_information",
1238                                 FT_BYTES, BASE_NONE,
1239                                 NULL,
1240                                 0x0,
1241                                 NULL,
1242                                 HFILL
1243                         }
1244                 },
1245                 {
1246                         &hf_release_token,
1247                         {
1248                                 "release token",
1249                                 "ses.release_token",
1250                                 FT_BOOLEAN, 8,
1251                                 NULL,
1252                                 RELEASE_TOKEN,
1253                                 NULL,
1254                                 HFILL
1255                         }
1256                 },
1257                 {
1258                         &hf_major_activity_token,
1259                         {
1260                                 "major/activity token",
1261                                 "ses.major.token",
1262                                 FT_BOOLEAN, 8,
1263                                 NULL,
1264                                 MAJOR_ACTIVITY_TOKEN,
1265                                 NULL,
1266                                 HFILL
1267                         }
1268                 },
1269                 {
1270                         &hf_synchronize_minor_token,
1271                         {
1272                                 "synchronize minor token",
1273                                 "ses.synchronize_token",
1274                                 FT_BOOLEAN, 8,
1275                                 NULL,
1276                                 SYNCHRONIZE_MINOR_TOKEN,
1277                                 NULL,
1278                                 HFILL
1279                         }
1280                 },
1281                 {
1282                         &hf_data_token,
1283                         {
1284                                 "data token",
1285                                 "ses.data_token",
1286                                 FT_BOOLEAN, 8,
1287                                 NULL,
1288                                 DATA_TOKEN,
1289                                 "data  token",
1290                                 HFILL
1291                         }
1292                 },
1293                 {
1294                         &hf_able_to_receive_extended_concatenated_SPDU,
1295                         {
1296                                 "Able to receive extended concatenated SPDU",
1297                                 "ses.connect.f1",
1298                                 FT_BOOLEAN, 8,
1299                                 NULL,
1300                                 SES_EXT_CONT,
1301                                 NULL,
1302                                 HFILL
1303                         }
1304                 },
1305                 {
1306                         &hf_session_user_req_flags,
1307                         {
1308                                 "Flags",
1309                                 "ses.req.flags",
1310                                 FT_UINT16,
1311                                 BASE_HEX,
1312                                 NULL,
1313                                 0x0,
1314                                 NULL,
1315                                 HFILL
1316                         }
1317                 },
1318                 {
1319                         &hf_session_exception_report,
1320                         {
1321                                 "Session exception report",
1322                                 "ses.exception_report.",
1323                                 FT_BOOLEAN, 16,
1324                                 NULL,
1325                                 SES_EXCEPTION_REPORT,
1326                                 NULL,
1327                                 HFILL
1328                         }
1329                 },
1330                 {
1331                         &hf_data_separation_function_unit,
1332                         {
1333                                 "Data separation function unit",
1334                                 "ses.data_sep",
1335                                 FT_BOOLEAN, 16,
1336                                 NULL,
1337                                 DATA_SEPARATION_FUNCTION_UNIT,
1338                                 NULL,
1339                                 HFILL
1340                         }
1341                 },
1342                 {
1343                         &hf_symmetric_synchronize_function_unit,
1344                         {
1345                                 "Symmetric synchronize function unit",
1346                                 "ses.symm_sync",
1347                                 FT_BOOLEAN, 16,
1348                                 NULL,
1349                                 SYMMETRIC_SYNCHRONIZE_FUNCTION_UNIT,
1350                                 NULL,
1351                                 HFILL
1352                         }
1353                 },
1354                 {
1355                         &hf_typed_data_function_unit,
1356                         {
1357                                 "Typed data function unit",
1358                                 "ses.typed_data",
1359                                 FT_BOOLEAN, 16,
1360                                 NULL,
1361                                 TYPED_DATA_FUNCTION_UNIT,
1362                                 NULL,
1363                                 HFILL
1364                         }
1365                 },
1366                 {
1367                         &hf_exception_function_unit,
1368                         {
1369                                 "Exception function unit",
1370                                 "ses.exception_data",
1371                                 FT_BOOLEAN, 16,
1372                                 NULL,
1373                                 EXCEPTION_FUNCTION_UNIT,
1374                                 NULL,
1375                                 HFILL
1376                         }
1377                 },
1378                 {
1379                         &hf_capability_function_unit,
1380                         {
1381                                 "Capability function unit",
1382                                 "ses.capability_data",
1383                                 FT_BOOLEAN, 16,
1384                                 NULL,
1385                                 CAPABILITY_DATA_FUNCTION_UNIT,
1386                                 NULL,
1387                                 HFILL
1388                         }
1389                 },
1390                 {
1391                         &hf_negotiated_release_function_unit,
1392                         {
1393                                 "Negotiated release function unit",
1394                                 "ses.negotiated_release",
1395                                 FT_BOOLEAN, 16,
1396                                 NULL,
1397                                 NEGOTIATED_RELEASE_FUNCTION_UNIT,
1398                                 NULL,
1399                                 HFILL
1400                         }
1401                 },
1402                 {
1403                         &hf_activity_management_function_unit,
1404                         {
1405                                 "Activity management function unit",
1406                                 "ses.activity_management",
1407                                 FT_BOOLEAN, 16,
1408                                 NULL,
1409                                 ACTIVITY_MANAGEMENT_FUNCTION_UNIT,
1410                                 NULL,
1411                                 HFILL
1412                         }
1413                 },
1414                 {
1415                         &hf_resynchronize_function_unit,
1416                         {
1417                                 "Resynchronize function unit",
1418                                 "ses.resynchronize",
1419                                 FT_BOOLEAN, 16,
1420                                 NULL,
1421                                 RESYNCHRONIZE_FUNCTION_UNIT,
1422                                 NULL,
1423                                 HFILL
1424                         }
1425                 },
1426                 {
1427                         &hf_major_resynchronize_function_unit,
1428                         {
1429                                 "Major resynchronize function unit",
1430                                 "ses.major_resynchronize",
1431                                 FT_BOOLEAN, 16,
1432                                 NULL,
1433                                 MAJOR_SYNCHRONIZE_FUNCTION_UNIT,
1434                                 NULL,
1435                                 HFILL
1436                         }
1437                 },
1438                 {
1439                         &hf_minor_resynchronize_function_unit,
1440                         {
1441                                 "Minor resynchronize function unit",
1442                                 "ses.minor_resynchronize",
1443                                 FT_BOOLEAN, 16,
1444                                 NULL,
1445                                 MINOR_SYNCHRONIZE_FUNCTION_UNIT,
1446                                 NULL,
1447                                 HFILL
1448                         }
1449                 },
1450                 {
1451                         &hf_expedited_data_resynchronize_function_unit,
1452                         {
1453                                 "Expedited data function unit",
1454                                 "ses.expedited_data",
1455                                 FT_BOOLEAN, 16,
1456                                 NULL,
1457                                 EXPEDITED_DATA_FUNCTION_UNIT,
1458                                 NULL,
1459                                 HFILL
1460                         }
1461                 },
1462                 {
1463                         &hf_duplex_function_unit,
1464                         {
1465                                 "Duplex functional unit",
1466                                 "ses.duplex",
1467                                 FT_BOOLEAN, 16,
1468                                 NULL,
1469                                 DUPLEX_FUNCTION_UNIT,
1470                                 NULL,
1471                                 HFILL
1472                         }
1473                 },
1474                 {
1475                         &hf_half_duplex_function_unit,
1476                         {
1477                                 "Half-duplex functional unit",
1478                                 "ses.half_duplex",
1479                                 FT_BOOLEAN, 16,
1480                                 NULL,
1481                                 HALF_DUPLEX_FUNCTION_UNIT,
1482                                 NULL,
1483                                 HFILL
1484                         }
1485                 },
1486                 {
1487                         &hf_proposed_tsdu_maximum_size_i2r,
1488                         {
1489                                 "Proposed TSDU Maximum Size, Initiator to Responder",
1490                                 "ses.proposed_tsdu_maximum_size_i2r",
1491                                 FT_UINT16,
1492                                 BASE_DEC,
1493                                 NULL,
1494                                 0x0,
1495                                 NULL,
1496                                 HFILL
1497                         }
1498                 },
1499                 {
1500                         &hf_proposed_tsdu_maximum_size_r2i,
1501                         {
1502                                 "Proposed TSDU Maximum Size, Responder to Initiator",
1503                                 "ses.proposed_tsdu_maximum_size_r2i",
1504                                 FT_UINT16,
1505                                 BASE_DEC,
1506                                 NULL,
1507                                 0x0,
1508                                 NULL,
1509                                 HFILL
1510                         }
1511                 },
1512                 {
1513                         &hf_protocol_version_1,
1514                         {
1515                                 "Protocol Version 1",
1516                                 "ses.protocol_version1",
1517                                 FT_BOOLEAN, 8,
1518                                 NULL,
1519                                 PROTOCOL_VERSION_1,
1520                                 NULL,
1521                                 HFILL
1522                         }
1523                 },
1524                 {
1525                         &hf_protocol_version_2,
1526                         {
1527                                 "Protocol Version 2",
1528                                 "ses.protocol_version2",
1529                                 FT_BOOLEAN, 8,
1530                                 NULL,
1531                                 PROTOCOL_VERSION_2,
1532                                 NULL,
1533                                 HFILL
1534                         }
1535                 },
1536                 {
1537                         &hf_initial_serial_number,
1538                         {
1539                                 "Initial Serial Number",
1540                                 "ses.initial_serial_number",
1541                                 FT_STRING, BASE_NONE,
1542                                 NULL,
1543                                 0x0,
1544                                 NULL,
1545                                 HFILL
1546                         }
1547                 },
1548                 {
1549                         &hf_beginning_of_SSDU,
1550                         {
1551                                 "beginning of SSDU",
1552                                 "ses.begininng_of_SSDU",
1553                                 FT_BOOLEAN, 8,
1554                                 NULL,
1555                                 BEGINNING_SPDU,
1556                                 NULL,
1557                                 HFILL
1558                         }
1559                 },
1560                 {
1561                         &hf_end_of_SSDU,
1562                         {
1563                                 "end of SSDU",
1564                                 "ses.end_of_SSDU",
1565                                 FT_BOOLEAN, 8,
1566                                 NULL,
1567                                 END_SPDU,
1568                                 NULL,
1569                                 HFILL
1570                         }
1571                 },
1572                 {
1573                         &hf_release_token_setting,
1574                         {
1575                                 "release token setting",
1576                                 "ses.release_token_setting",
1577                                 FT_UINT8, BASE_HEX,
1578                                 VALS(token_setting_vals),
1579                                 0xC0,
1580                                 NULL,
1581                                 HFILL
1582                         }
1583                 },
1584                 {
1585                         &hf_major_activity_token_setting,
1586                         {
1587                                 "major/activity setting",
1588                                 "ses.major_activity_token_setting",
1589                                 FT_UINT8, BASE_HEX,
1590                                 VALS(token_setting_vals),
1591                                 0x30,
1592                                 "major/activity token setting",
1593                                 HFILL
1594                         }
1595                 },
1596                 {
1597                         &hf_synchronize_minor_token_setting,
1598                         {
1599                                 "synchronize-minor token setting",
1600                                 "ses.synchronize_minor_token_setting",
1601                                 FT_UINT8, BASE_HEX,
1602                                 VALS(token_setting_vals),
1603                                 0x0C,
1604                                 NULL,
1605                                 HFILL
1606                         }
1607                 },
1608                 {
1609                         &hf_data_token_setting,
1610                         {
1611                                 "data token setting",
1612                                 "ses.data_token_setting",
1613                                 FT_UINT8, BASE_HEX,
1614                                 VALS(token_setting_vals),
1615                                 0x03,
1616                                 NULL,
1617                                 HFILL
1618                         }
1619                 },
1620                 {
1621                         &hf_activity_identifier,
1622                         {
1623                                 "Activity Identifier",
1624                                 "ses.activity_identifier",
1625                                 FT_UINT32, BASE_DEC,
1626                                 NULL,
1627                                 0x0,
1628                                 NULL,
1629                                 HFILL
1630                         }
1631                 },
1632                 {
1633                         &hf_serial_number,
1634                         {
1635                                 "Serial Number",
1636                                 "ses.serial_number",
1637                                 FT_STRING, BASE_NONE,
1638                                 NULL,
1639                                 0x0,
1640                                 NULL,
1641                                 HFILL
1642                         }
1643                 },
1644                 {
1645                         &hf_calling_session_selector,
1646                         {
1647                                 "Calling Session Selector",
1648                                 "ses.calling_session_selector",
1649                                 FT_BYTES, BASE_NONE,
1650                                 NULL,
1651                                 0x0,
1652                                 NULL,
1653                                 HFILL
1654                         }
1655                 },
1656                 {
1657                         &hf_called_session_selector,
1658                         {
1659                                 "Called Session Selector",
1660                                 "ses.called_session_selector",
1661                                 FT_BYTES, BASE_NONE,
1662                                 NULL,
1663                                 0x0,
1664                                 NULL,
1665                                 HFILL
1666                         }
1667                 },
1668                 {
1669                         &hf_second_serial_number,
1670                         {
1671                                 "Second Serial Number",
1672                                 "ses.second_serial_number",
1673                                 FT_STRING, BASE_NONE,
1674                                 NULL,
1675                                 0x0,
1676                                 NULL,
1677                                 HFILL
1678                         }
1679                 },
1680                 {
1681                         &hf_second_initial_serial_number,
1682                         {
1683                                 "Second Initial Serial Number",
1684                                 "ses.second_initial_serial_number",
1685                                 FT_STRING, BASE_NONE,
1686                                 NULL,
1687                                 0x0,
1688                                 NULL,
1689                                 HFILL
1690                         }
1691                 },
1692                 {
1693                         &hf_large_initial_serial_number,
1694                         {
1695                                 "Large Initial Serial Number",
1696                                 "ses.large_initial_serial_number",
1697                                 FT_STRING, BASE_NONE,
1698                                 NULL,
1699                                 0x0,
1700                                 NULL,
1701                                 HFILL
1702                         }
1703                 },
1704                 {
1705                         &hf_large_second_initial_serial_number,
1706                         {
1707                                 "Large Second Initial Serial Number",
1708                                 "ses.large_second_initial_serial_number",
1709                                 FT_STRING, BASE_NONE,
1710                                 NULL,
1711                                 0x0,
1712                                 NULL,
1713                                 HFILL
1714                         }
1715                 },
1716                 {
1717                         &hf_connect_protocol_options_flags,
1718                         {
1719                                 "Flags",
1720                                 "ses.connect.flags",
1721                                 FT_UINT8,
1722                                 BASE_HEX,
1723                                 NULL,
1724                                 0x0,
1725                                 NULL,
1726                                 HFILL
1727                         }
1728                 },
1729                 {
1730                         &hf_version_number_options_flags,
1731
1732                         {
1733                                 "Flags",
1734                                 "ses.version.flags",
1735                                 FT_UINT8,
1736                                 BASE_HEX,
1737                                 NULL,
1738                                 0x0,
1739                                 NULL,
1740                                 HFILL
1741                         }
1742                 },
1743
1744                 {
1745                         &hf_token_item_options_flags,
1746
1747                         {
1748                                 "Flags",
1749                                 "ses.tken_item.flags",
1750                                 FT_UINT8,
1751                                 BASE_HEX,
1752                                 NULL,
1753                                 0x0,
1754                                 NULL,
1755                                 HFILL
1756                         }
1757                 },
1758
1759                 {
1760                         &hf_enclosure_item_options_flags,
1761
1762                         {
1763                                 "Flags",
1764                                 "ses.enclosure.flags",
1765                                 FT_UINT8,
1766                                 BASE_HEX,
1767                                 NULL,
1768                                 0x0,
1769                                 NULL,
1770                                 HFILL
1771                         }
1772                 },
1773         };
1774
1775         static gint *ett[] =
1776         {
1777                 &ett_ses,
1778                 &ett_ses_param,
1779                 &ett_connect_protocol_options_flags,
1780                 &ett_protocol_version_flags,
1781                 &ett_enclosure_item_flags,
1782                 &ett_token_item_flags,
1783                 &ett_ses_req_options_flags,
1784         };
1785 /*      module_t *ses_module; */
1786
1787
1788         proto_ses = proto_register_protocol(PROTO_STRING_SES, "SES", "ses");
1789         proto_register_field_array(proto_ses, hf, array_length(hf));
1790         proto_register_subtree_array(ett, array_length(ett));
1791
1792 /*
1793         ses_module = prefs_register_protocol(proto_ses, NULL);
1794
1795         prefs_register_bool_preference(ses_module, "desegment",
1796             "Reassemble session packets ",
1797             "Whether the session dissector should reassemble messages spanning multiple SES segments",
1798             &ses_desegment);  */
1799
1800         /*
1801          * Register the dissector by name, so other dissectors can
1802          * grab it by name rather than just referring to it directly
1803          * (you can't refer to it directly from a plugin dissector
1804          * on Windows without stuffing it into the Big Transfer Vector).
1805          */
1806         register_dissector("ses", dissect_ses, proto_ses);
1807 }
1808
1809 static gboolean
1810 dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1811 {
1812         /* must check that this really is a ses packet */
1813         int offset = 0;
1814         guint8 type;
1815         int len_len;
1816         guint16 len;
1817
1818         /* first, check do we have at least 4 bytes (type+length) */
1819         if (tvb_length(tvb) < 2)
1820                 return FALSE;   /* no */
1821
1822         /* can we recognize session PDU ? Return FALSE if  not */
1823         /*   get SPDU type */
1824         type = tvb_get_guint8(tvb, offset);
1825         /* check SPDU type */
1826         if (match_strval(type, ses_vals) == NULL)
1827         {
1828                 return FALSE;  /* no, it isn't a session PDU */
1829         }
1830
1831         /* can we recognize the second session PDU if the first one was
1832          * a Give Tokens PDU? Return FALSE if not */
1833         if(tvb_bytes_exist(tvb, 2, 2) && type == SES_GIVE_TOKENS) {
1834                 /*   get SPDU type */
1835                 type = tvb_get_guint8(tvb, offset+2);
1836                 /* check SPDU type */
1837                 if (match_strval(type, ses_vals) == NULL)
1838                         {
1839                                 return FALSE;  /* no, it isn't a session PDU */
1840                         }
1841         }
1842
1843         /* some Siemens SIMATIC protocols also use COTP, and shouldn't be 
1844          * misinterpreted as SES.
1845          * the starter in this case is fixed to 0x32 (SES_MINOR_SYNC_ACK for SES), 
1846          * so if the parameter type is unknown, it's probably SIMATIC */
1847         if(type == 0x32 && tvb_length(tvb) >= 3) {
1848                 type = tvb_get_guint8(tvb, offset+2);
1849                 if (match_strval(type, param_vals) == NULL) {
1850                         return FALSE; /* it's probably a SIMATIC protocol */
1851                 }
1852         }
1853
1854         /*  OK,let's check SPDU length  */
1855         /*  get length of SPDU */
1856         len = get_item_len(tvb, offset+1, &len_len);
1857
1858         /*  add header length     */
1859         len+=len_len;
1860         /* do we have enough bytes ? */
1861         if (tvb_length(tvb) < len)
1862                 return FALSE;   /* no */
1863
1864         dissect_ses(tvb, pinfo, parent_tree);
1865         return TRUE;
1866 }
1867
1868 void
1869 proto_reg_handoff_ses(void)
1870 {
1871         /*   find data dissector  */
1872         data_handle = find_dissector("data");
1873
1874         /* define sub dissector */
1875         pres_handle = find_dissector("pres");
1876
1877         /* add our session dissector to cotp dissector list 
1878          * and cotp_is dissector list*/
1879         heur_dissector_add("cotp", dissect_ses_heur, proto_ses);
1880         heur_dissector_add("cotp_is", dissect_ses_heur, proto_ses);
1881 }