push one more object into the session structure so acse can pick it up later.
[obnox/wireshark/wip.git] / epan / dissectors / packet-pres.c
1 /* packet-pres.c
2 *
3 * Routine to dissect ISO 8823 OSI Presentation Protocol packets
4 *
5 * $Id$
6 *
7 * Yuriy Sidelnikov <YSidelnikov@hotmail.com>
8 *
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@ethereal.com>
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 "packet-pres.h"
39 #include "packet-frame.h"
40 #include <epan/prefs.h>
41
42 #include <epan/strutil.h>
43
44 #include <epan/asn1.h>
45 #include "format-oid.h"
46
47 #include "packet-ses.h"
48 extern const value_string ses_vals[];
49
50 /* pres header fields             */
51 static int proto_pres          = -1;
52 /*   type of session envelop */
53 static struct SESSION_DATA_STRUCTURE* session = NULL;
54 static int hf_pres_rc_type                      = -1;
55 static int hf_pres_ms_type                      = -1;
56 static int hf_pres_seq_type                     = -1;
57 static int hf_pres_protocol_version =-1;
58 /* pres fields defining a sub tree */
59 static gint ett_pres           = -1;
60 static gint ett_pres_param     = -1;
61 static gint ett_pres_rc           = -1;
62 static gint ett_pres_ms           = -1;
63 static gint ett_pres_itm           = -1;
64
65 /*
66 ----------------------------------------------------------------------------------------------------------*/
67 static dissector_handle_t acse_handle = NULL;
68
69 static int hf_pres_type        = -1;
70 static int hf_pres_length      = -1;
71 static int hf_value                        = -1;
72
73
74 static int hf_cp_type_message_length = -1;
75
76 static int hf_protocol_version       = -1;
77 static int hf_context_management       = -1;
78 static int hf_restoration       = -1;
79
80
81 static const value_string pres_vals[] =
82 {
83   {PRES_CONNECTION_REQUEST_CONFIRM,  "Connection request/confirm PDU" },
84   {PRES_CONNECTION_REFUSE,    "Connection refuse PDU"   },
85   {0,             NULL           }
86 };
87
88 static const value_string cr_vals[] =
89 {
90   {MODE_SELECTOR, "Mode Selector"},
91   {SEQUENCE_TOP, "Sequence"},
92   {SET_TOP, "Set"},
93   {0, NULL}
94 };
95
96 static const value_string sequence_top_vals[] =
97 {
98   {CALLED_PRESENTATION_SELECTOR, "Called presentation selector"},
99   {CALLING_PRESENTATION_SELECTOR, "Calling presentation selector"},
100   {PRESENTATION_CONTEXT_DEFINITION_LIST, "Presentation context definition list"},
101   {RESPONDING_PRESENTATION_SELECTOR, "Responding presentation selector"},
102   {PROTOCOL_VERSION, "Protocol version"},
103   {PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST, "Presentation context definition result list"},
104   {PRESENTATION_REQUIREMENTS,"Presentation requirements"},
105   {DEFAULT_CONTEXT_NAME,"Default context name"},
106   {USER_SESSION_REQUIREMENTS,"User session requirements"},
107   {DEFAULT_CONTEXT_RESULT,"Default context result"},
108   {PROVIDER_REASON,"Provider reason"},
109   {0, NULL}
110 };
111 static const value_string sequence_list_vals[] =
112 {
113   {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
114   {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
115   {TRANSFER_SYNTAX_NAMES,"Transfer syntax names"},
116   {0, NULL}
117 };
118 static const value_string sequence_list_result_vals[] =
119 {
120   {PRESENTATION_RESULT,"Result"},
121   {PRESENTATION_RESULT_INTEGER,"Integer"},
122   {PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME,"Transfer syntax name"},
123   {0, NULL}
124 };
125 static const value_string presentation_context_definition_vals[] =
126 {
127   {SEQUENCE, "Sequence"},
128   {0, NULL}
129 };
130 static const value_string sequence_list_result_values_vals[] =
131 {
132   {PRESENTATION_RESULT_ACCEPTANCE,"Acceptance"},
133   {PRESENTATION_RESULT_USER_REJECTION,"User rejection"},
134   {PRESENTATION_RESULT_PROVIDER_REJECTION,"Provider rejection"},
135   {0, NULL}
136 };
137 static const value_string provider_reason_values_vals[] =
138 {
139   {REASON_NOT_SPECIFIED,"Reason not specified"},
140   {TEMPORARY_CONGESTION,"Temporary congestion"},
141   {LOCAL_LIMIT_EXCEEDED,"Local limit exceeded"},
142   {CALLED_PRESENTATION_ADDRESS_UNKNOWN,"Called presentation address unknown"},
143   {PROTOCOL_VERSION_NOT_SUPPORTED,"Protocol version not supported"},
144   {DEFAULT_CONTEXT_NOT_SUPPORTED,"Default context not supported"},
145   {USER_DATA_NOT_READABLE,"User data not readable"},
146   {NO_PSAP_AVAILABLE,"No PSAP available"},
147   {0, NULL}
148 };
149
150 static const value_string user_data_values_vals[] =
151 {
152   {SIMPLY_ENCODED_DATA,"Simply encoded data"},
153   {FULLY_ENCODED_DATA,"Fully encoded data "},
154   {0, NULL}
155 };
156 static const value_string presentation_data_values[] =
157 {
158   {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
159   {SINGLE_ASN1_TYPE,"Single ASN.1 type"},
160   {OCTET_ALIGNED,"Octet aligned"},
161   {ARBITRARY,"Arbitrary"},
162   {DATA_BLOCK,"Data block"},
163   {0, NULL}
164 };
165 static const value_string provider_abort_values_vals[] =
166 {
167   {PR_REASON_NOT_SPECIFIED,"Reason not specified"},
168   {UNRECOGNIZED_PDU,"Unrecognized ppdu"},
169   {UNEXPECTED_PDU,"Unexpected ppdu"},
170   {UNEXPECTED_SESSION_SERVICE_PRIMITIVE,"Unexpected session service primitive"},
171   {UNRECOGNIZED_PPDU_PARAMETER,"Unrecognized ppdu parameter"},
172   {UNEXPECTED_PPDU_PARAMETER,"Unexpected ppdu parameter"},
173   {INVALID_PPDU_PARAMETER_VALUE,"Invalid ppdu parameter value"},
174   {0, NULL}
175 };
176 static const value_string event_identifier_values_vals[] =
177 {
178   {REASON_CP_PPDU,"cp PPDU"},
179   {REASON_CPA_PPDU,"cpa PPDU"},
180   {REASON_CPR_PPDU,"cpr PPDU"},
181   {REASON_ARU_PPDU,"aru PPDU"},
182   {REASON_ARP_PPDU,"arp PPDU"},
183   {REASON_AC_PPDU,"ac PPDU"},
184   {REASON_ACA_PPDU,"aca PPDU"},
185   {REASON_TD_PPDU,"td PPDU"},
186   {REASON_TTD_PPDU,"td PPDU"},
187   {REASON_TE_PPDU,"te PPDU"},
188   {REASON_TC_PPDU,"tc PPDU"},
189   {REASON_TCC_PPDU,"tcc PPDU"},
190   {REASON_RS_PPDU,"rs PPDU"},
191   {REASON_RSA_PPDU,"rsa PPDU"},
192   {S_RELEASE_INDICATION,"s release indication"},
193   {S_RELEASE_CONFIRM,"s release confirm"},
194   {S_TOKEN_GIVE_INDICATION,"s token give indication"},
195   {S_TOKEN_PLEASE_INDICATION,"s token please indication"},
196   {S_CONTROL_GIVE_INDICATION,"s control give indication"},
197   {S_SYNC_MINOR_INDICATION,"s sync minor indication"},
198   {S_SYNC_MINOR_CONFIRM,"s sync minor confirm"},
199   {S_SYNC_MAJOR_INDICATION,"s sync major indication"},
200   {S_SYNC_MAJOR_CONFIRM,"s sync major confirm"},
201   {S_P_EXCEPTION_REPORT_INDICATION,"s p exception report indication"},
202   {S_U_EXCEPTION_REPORT_INDICATION,"s u exception report indication"},
203   {S_ACTIVITY_START_INDICATION,"s activity start indication"},
204   {S_ACTIVITY_RESUME_INDICATION,"s activity resume indication"},
205   {S_ACTIVITY_INTERRUPT_INDICATION,"s activity interrupt indication"},
206   {S_ACTIVITY_INTERRUPT_CONFIRM,"s activity interrupt confirm"},
207   {S_ACTIVITY_DISCARD_INDICATION,"s activity discard indication"},
208   {S_ACTIVITY_DISCARD_CONFIRM,"s activity discard confirm"},
209   {S_ACTIVITY_END_INDICATION,"s activity end indication"},
210   {S_ACTIVITY_END_CONFIRM,"s activity end confirm"},
211   {0, NULL}
212 };
213 /*      pointers for acse dissector  */
214 proto_tree *global_tree  = NULL;
215 packet_info *global_pinfo = NULL;
216 /* dissector for data */
217 static dissector_handle_t data_handle;
218
219 static void
220 call_acse_dissector(tvbuff_t *tvb, gint offset, gint param_len,
221     packet_info *pinfo, proto_tree *tree, proto_tree *param_tree)
222 {
223         /* do we have OSI acse/rose packet dissector ? */
224         if(!acse_handle)
225         {
226                 /* No - display as data */
227                 if (tree)
228                 {
229                         proto_tree_add_text(param_tree, tvb, offset, param_len,
230                             "No ACSE dissector available");
231                 }
232         }
233         else
234         {
235                 /* Yes - call app dissector */
236                 tvbuff_t *next_tvb;
237
238                 next_tvb = tvb_new_subset(tvb, offset, param_len, param_len);
239                 TRY
240                 {
241                         call_dissector(acse_handle, next_tvb, pinfo, tree);
242                 }
243                 CATCH_ALL
244                 {
245                         show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
246                 }
247                 ENDTRY;
248         }
249 }
250
251 static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
252 {
253   guint length = 0;
254   gboolean def = FALSE;
255   int start = a->offset;
256   int ret;
257
258   ret = asn1_length_decode(a, &def, &length);
259   if (ret != ASN1_ERR_NOERROR)
260   {
261     if (tree)
262         {
263       proto_tree_add_text(tree, a->tvb, start, 0,
264         "%s: ERROR: Couldn't parse length: %s",
265         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
266     }
267     return ret;
268   }
269
270   if (len)
271     *len = length;
272
273   if (hf_id)
274     proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start, 
275 length);
276
277   return ASN1_ERR_NOERROR;
278 }
279 static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
280         proto_item **new_item, guint *i, int start, guint length)
281 {
282   guint integer = 0;
283   proto_item *temp_item = NULL;
284   int ret;
285
286   ret = asn1_uint32_value_decode(a, length, &integer);
287   if (ret != ASN1_ERR_NOERROR)
288   {
289     if (tree)
290         {
291       proto_tree_add_text(tree, a->tvb, start, 0,
292        "%s: ERROR: Couldn't parse value: %s",
293         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
294     }
295     return ret;
296   }
297
298   if (i)
299     *i = integer;
300
301   if (hf_id)
302     temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start, 
303 a->offset-start, integer);
304
305   if (new_item)
306     *new_item = temp_item;
307
308   return ASN1_ERR_NOERROR;
309 }
310
311 static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
312         proto_item **new_item, guint *i)
313 {
314   guint cls, con, tag;
315   gboolean def;
316   guint length;
317   int start = a->offset;
318   int ret;
319
320   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
321   if (ret != ASN1_ERR_NOERROR)
322   {
323     if (tree)
324         {
325       proto_tree_add_text(tree, a->tvb, start, 0,
326         "%s: ERROR: Couldn't parse header: %s",
327         (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
328         asn1_err_to_str(ret));
329     }
330     return ret;
331   }
332
333   return read_integer_value(a, tree, hf_id, new_item, i, start, length);
334 }
335 /*   display asn.1 Integer type */
336 static void
337 show_integer(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int 
338 *offset,int item_len)
339 {
340           proto_tree *pres_tree_itm = NULL;
341           proto_item *itm;
342           int       ret;
343           int           save_len = item_len;
344           int           off      = *offset;
345           itm = proto_tree_add_text(pres_tree, tvb, *offset, item_len,
346                                                                                 "Integer");
347           pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
348           ret = read_integer(asn,pres_tree_itm,0,NULL,&item_len);
349           if (ret == ASN1_ERR_NOERROR )
350                         {
351                                 *offset = asn->offset;
352                                 itm = proto_tree_add_text(pres_tree_itm, tvb, (*offset)-item_len, 
353 item_len,
354                                                                                         "Integer value: %u",item_len);
355                         }
356           else
357                         {
358                   /* can't dissect item. Skip it. */
359                   *offset = off+ save_len;
360                         }
361
362 }
363 static void
364 show_presentation_requirements(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t 
365 *tvb,int *offset,int item_len,int tag)
366 {
367           proto_tree *pres_tree_itm = NULL;
368           proto_item *itm;
369           guint16       flags;
370           gint length;
371 /* do we have enough bytes to dissect this item ? */
372                         if( ( length = tvb_reported_length_remaining(tvb, *offset))  < 
373 (asn->offset -*offset)+ item_len )
374                         {
375                                         proto_tree_add_text(pres_tree, tvb, *offset, item_len,
376                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
377                                         return;
378                         }
379
380           itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+ 
381 item_len,
382                                                                                         val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
383           pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
384           *offset = asn->offset;
385           flags = tvb_get_ntohs(tvb, *offset);
386           proto_tree_add_boolean(pres_tree_itm,hf_context_management, tvb, *offset, 
387 2, flags);
388           proto_tree_add_boolean(pres_tree_itm,hf_restoration, tvb, *offset, 2, 
389 flags);
390           *offset = *offset + item_len;
391           asn->offset = *offset;
392 }
393
394 static void
395 show_protocol_version(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int 
396 *offset,int item_len,int tag)
397 {
398           proto_tree *pres_tree_itm = NULL;
399           proto_item *itm;
400           guint16       flags;
401           gint length;
402 /* do we have enough bytes to dissect this item ? */
403                         if( ( length = tvb_reported_length_remaining(tvb, *offset))  < 
404 (asn->offset -*offset)+ item_len )
405                         {
406                                         proto_tree_add_text(pres_tree, tvb, *offset, item_len,
407                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
408                                         return;
409                         }
410
411           itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+ 
412 item_len,
413                                                                                         val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
414           pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
415           *offset = asn->offset;
416           flags = tvb_get_ntohs(tvb, *offset);
417           proto_tree_add_boolean(pres_tree_itm,hf_protocol_version, tvb, *offset, 
418 2, flags);
419           *offset = *offset + item_len;
420           asn->offset = *offset;
421 }
422 static void
423 print_oid_value(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int 
424 *offset,int item_len)
425 {
426         guint           ret;
427         subid_t         *oid;
428         guint           len;
429         gchar           *display_string;
430         guint           length;
431         guint           start=*offset;
432
433                 ret = asn1_oid_value_decode (asn, item_len, &oid, &len);
434                 if (ret != ASN1_ERR_NOERROR)
435                 {
436                         return ;
437                 }
438                 length = asn->offset - start;
439                 display_string = format_oid(oid, len);
440                 proto_tree_add_text(pres_tree, tvb, *offset,length,"Value:%s", 
441 display_string);
442                 g_free(display_string);
443                 (*offset)=start+item_len;
444                 asn->offset = (*offset);
445 }
446 static void
447 print_oid(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int *offset,int 
448 item_len)
449 {
450         guint           ret;
451         subid_t         *oid;
452         guint           len;
453         guint           nbytes;
454         gchar           *display_string;
455         guint           length;
456         guint           start=*offset;
457
458                 ret = asn1_oid_decode ( asn, &oid, &len, &nbytes);
459
460                 if (ret != ASN1_ERR_NOERROR)
461                 {
462                         return ;
463                 }
464                 length = asn->offset - start;
465                 display_string = format_oid(oid, len);
466                 proto_tree_add_text(pres_tree, tvb, *offset,length,"Value:%s", 
467 display_string);
468                 g_free(display_string);
469                 (*offset)=start+item_len;
470                 asn->offset = (*offset);
471 }
472
473 static void
474 print_value(ASN1_SCK *asn,proto_tree *pres_tree, tvbuff_t *tvb, int *offset, int item_len)
475 {
476     gint    start = *offset;
477     gchar  *tmp;
478
479     *offset = asn->offset;  /* align to data*/
480     tmp = tvb_bytes_to_str(tvb, *offset, item_len);
481     proto_tree_add_text(pres_tree, tvb, *offset, item_len, tmp);
482     (*offset) = start+item_len;
483     asn->offset = (*offset);
484 }
485
486 static int
487 get_integer_value(ASN1_SCK *asn,int length,int *offset)
488 {
489         int off = *offset;
490         int asn_off = asn->offset;
491         int item_len = -1;
492         int ret;
493         /* align   pointers */
494         *offset=asn->offset;
495         ret = asn1_uint32_value_decode(asn, length, &item_len);
496         /* return to present position */
497         *offset = off;
498         asn->offset = asn_off;
499
500     if (ret != ASN1_ERR_NOERROR )
501         {
502                 return -1;
503         }
504         else
505         {
506                 return item_len;
507         }
508
509 }
510 static void
511 show_presentation_context_definition_result_seq(ASN1_SCK *asn,proto_tree 
512 *pres_tree,tvbuff_t *tvb,int *offset,int item_len)
513 {
514           proto_tree *pres_tree_ms = NULL;
515           guint length;
516           guint   type;
517           proto_item *ms;
518           guint   new_item_len;
519           guint   start = *offset;
520           guint   header_len;
521           int           old_offset;
522
523                         /*  print seq */
524                         while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
525                         {
526                                 old_offset = *offset ;
527                         /*  get item type  */
528                         type = tvb_get_guint8(tvb, *offset);
529                         /* skip type */
530                         (*offset)++;
531                         asn->offset = *offset;
532                         /* get length  */
533                                 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
534                                 {
535                                         (*offset)=start+item_len;
536                                         asn->offset = (*offset);
537                                         return  ;
538                                 }
539
540                         /* do we have enough bytes to dissect ? */
541                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < 
542 new_item_len )
543                         {
544                                         proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
545                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
546                                         (*offset)=start+item_len;
547                                         asn->offset = (*offset);
548                                     return ;
549                         }
550                                 header_len = asn->offset - (*offset) +1;
551                                 ms = proto_tree_add_text(pres_tree, tvb, *offset-1, 
552 new_item_len+(asn->offset-*offset)+1,
553                                                                                 val_to_str(type, sequence_list_result_vals,
554                                                                                 "Unknown item (0x%02x)"));
555                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
556                                 *offset = asn->offset;
557
558
559                         switch(type)
560                                 {
561                         case PRESENTATION_RESULT:
562                                 {
563                                         proto_tree *pres_tree_pr = NULL;
564                                         proto_item *pr;
565                                         int        value        =       get_integer_value(asn,new_item_len,offset);
566                                 pr = proto_tree_add_text(pres_tree_ms, tvb, *offset, 
567 new_item_len+(asn->offset-*offset),
568                                                                 val_to_str(value ,sequence_list_result_values_vals,
569                                                                 "Unknown item (0x%02x)"));
570                                 pres_tree_pr = proto_item_add_subtree(pr, ett_pres_ms);
571
572                                 print_value(asn,pres_tree_pr,tvb,offset,new_item_len);
573                                 }
574                                         break;
575                         case PRESENTATION_RESULT_INTEGER:
576                                 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
577                                         break;
578                         case PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME:
579                                 print_oid_value(asn,pres_tree_ms,tvb,offset,new_item_len);
580                                         break;
581
582                         default:
583                                         proto_tree_add_text(pres_tree, tvb, *offset, 
584 new_item_len+(asn->offset-*offset),
585                                         "Unknown asn.1 parameter: (0x%02x)", type);
586                                 }
587                                 *offset = old_offset+new_item_len+header_len;
588                                 item_len-=new_item_len+header_len;
589                         }
590                         /*   align the pointer */
591                         (*offset)=start+item_len;
592                         asn->offset = (*offset);
593 }
594
595 static void
596 show_presentation_context_definition_seq(ASN1_SCK *asn,proto_tree 
597 *pres_tree,tvbuff_t *tvb,int *offset,int item_len)
598 {
599           proto_tree *pres_tree_ms = NULL;
600           guint length;
601           guint   type;
602           proto_item *ms;
603           guint   new_item_len;
604           guint   start = *offset;
605           guint   header_len;
606           int           old_offset;
607
608                         /*  print seq */
609                         while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
610                         {
611                                 old_offset = *offset ;
612                         /*  get item type  */
613                         type = tvb_get_guint8(tvb, *offset);
614                         /* skip type */
615                         (*offset)++;
616                         asn->offset = *offset;
617                         /* get length  */
618                                 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
619                                 {
620                                         (*offset)=start+item_len;
621                                         asn->offset = (*offset);
622                                         return  ;
623                                 }
624
625                         /* do we have enough bytes to dissect ? */
626                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < 
627 new_item_len )
628                         {
629                                         proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
630                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
631                                         (*offset)=start+item_len;
632                                         asn->offset = (*offset);
633                                     return ;
634                         }
635                                 header_len = asn->offset - (*offset) +1;
636                                 ms = proto_tree_add_text(pres_tree, tvb, *offset-1, 
637 new_item_len+(asn->offset-*offset)+1,
638                                                                                 val_to_str(type, sequence_list_vals,
639                                                                                 "Unknown item (0x%02x)"));
640                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
641                                 *offset = asn->offset;
642
643
644                         switch(type)
645                                 {
646                         case PRESENTATION_CONTEXT_IDENTIFIER:
647                                 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
648                                         break;
649                         case ABSTRACT_SYNTAX_NAME:
650                                 print_oid_value(asn,pres_tree_ms,tvb,offset,new_item_len);
651                                         break;
652                         case TRANSFER_SYNTAX_NAMES:
653                                 print_oid(asn,pres_tree_ms,tvb,offset,new_item_len);
654                                         break;
655                         default:
656                                         proto_tree_add_text(pres_tree, tvb, *offset, 
657 new_item_len+(asn->offset-*offset),
658                                         "Unknown asn.1 parameter: (0x%02x)", type);
659                                 }
660                                 *offset = old_offset+new_item_len+header_len;
661                                 item_len-=new_item_len+header_len;
662                         }
663                         /*   align the pointer */
664                         (*offset)=start+item_len;
665                         asn->offset = (*offset);
666 }
667 static void
668 show_fully_encoded_seq(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int 
669 *offset,int item_len)
670 {
671           proto_tree *pres_tree_ms = NULL;
672           guint length;
673           guint   type;
674           proto_item *ms;
675           guint   new_item_len;
676           guint   start = *offset;
677           guint   header_len;
678           guint   acse = 0;      /*   no acse   id   */
679           int           old_offset;
680                         /*  print seq */
681                         while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
682                         {
683                                 old_offset = *offset ;
684                         /*  get item type  */
685                         type = tvb_get_guint8(tvb, *offset);
686                         /* skip type */
687                         (*offset)++;
688                         asn->offset = *offset;
689                         /* get length  */
690                                 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
691                                 {
692                                         (*offset)=start+item_len;
693                                         asn->offset = (*offset);
694                                         return  ;
695                                 }
696                         /* do we have enough bytes to dissect ? */
697                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < 
698 new_item_len )
699                         {
700                                         proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
701                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
702                                         (*offset)=start+item_len;
703                                         asn->offset = (*offset);
704                                     return ;
705                         }
706                         if(!new_item_len && length>2)
707                         {
708                                         new_item_len = length-1;  /* can't get length from asn1 tag. Use rest of the pdu len. */
709                         }
710                                 header_len = asn->offset - (*offset) +1;
711                                 ms = proto_tree_add_text(pres_tree, tvb, *offset-1, 
712 new_item_len+(asn->offset-*offset)+1,
713                                                                                 val_to_str(type, presentation_data_values,
714                                                                                 "Unknown item (0x%02x)"));
715                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
716                                 *offset = asn->offset;
717
718
719                         switch(type)
720                                 {
721                         case PRESENTATION_CONTEXT_IDENTIFIER:
722                                 {
723                                 acse    =       get_integer_value(asn,new_item_len,offset);
724                                 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
725                                 if(session){
726                                         session->pres_ctx_id=acse;
727                                 }
728                                 }
729                                         break;
730                         case OCTET_ALIGNED:
731                         case DATA_BLOCK:
732                                 {
733                                                 proto_item *acse_ms;
734                                         /*  yes, we have to call ACSE dissector    */
735                                 acse_ms = proto_tree_add_text(pres_tree_ms, tvb, *offset,new_item_len+(asn->offset-*offset),
736                                                                                 "User data");
737
738                                 session->abort_type = DATA_BLOCK;
739                                         /*  call acse dissector  */
740                                 call_acse_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,pres_tree_ms);
741                                 }
742                                         break;
743                         case SINGLE_ASN1_TYPE:
744
745                                 {
746                                                 proto_item *acse_ms;
747                                         /*  yes, we have to call ACSE dissector    */
748                                 acse_ms = proto_tree_add_text(pres_tree_ms, tvb, *offset, 
749 new_item_len+(asn->offset-*offset),
750                                                                                 "User data");
751                                         /*  call acse dissector  */
752                                 call_acse_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,pres_tree_ms);
753                                 acse = 0;
754                                 }
755                                         break;
756                         case ARBITRARY:
757                                 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
758                                         break;
759                         default:
760                                         proto_tree_add_text(pres_tree, tvb, *offset, 
761 new_item_len+(asn->offset-*offset),
762                                         "Unknown asn.1 parameter: (0x%02x)", type);
763                                 }
764                                 *offset = old_offset+new_item_len+header_len;
765                                 item_len-=new_item_len+header_len;
766                         }
767                         /*   align the pointer */
768                         (*offset)=start+item_len;
769                         asn->offset = (*offset);
770
771 }
772 static void
773 show_fully_encoded_data(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t 
774 *tvb,int *offset,int item_len)
775 {
776           proto_tree *pres_tree_ms = NULL;
777           proto_tree *pres_tree_pc = NULL;
778           gint    length;
779           guint   type;
780           guint   header_len;
781           proto_item *ms;
782           gint   new_item_len;
783           guint   start = asn->offset;
784           guint   item_length = item_len;
785           pres_tree_pc = pres_tree;
786
787 /* do we have enough bytes to dissect ? */
788                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
789                         {
790                                         proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
791                                                         "Wrong item.Need %u bytes but have %u", item_len,length);
792                                         /*   align the pointer */
793                                         (*offset)=start+item_length;
794                                         asn->offset = (*offset);
795                                         return ;
796                         }
797                         *offset =asn->offset;
798                         start = *offset;
799                         /*  read the rest */
800                         while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
801                         {
802                                 int old_offset = *offset;
803                         /*  get item type  */
804                         type = tvb_get_guint8(tvb, *offset);
805                         /* skip type */
806                         (*offset)++;
807                         asn->offset = *offset;
808                         /* get length  */
809                                 if (read_length(asn, pres_tree_pc, 0, &new_item_len) != 
810 ASN1_ERR_NOERROR)
811                                 {
812                                         /*   align the pointer */
813                                         (*offset)=start+item_length;
814                                         asn->offset = (*offset);
815                                         return  ;
816                                 }
817                                 header_len = asn->offset - (*offset) +1;
818                         /* do we have enough bytes to dissect ? */
819                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < 
820 new_item_len )
821                         {
822                                         proto_tree_add_text(pres_tree_pc, tvb, *offset, new_item_len,
823                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
824                                         /*   align the pointer */
825                                         (*offset)=start+item_length;
826                                         asn->offset = (*offset);
827                                         return ;
828                         }
829                         if(!new_item_len && length>2)
830                         {
831                                 /* check if really do have what to dissect */
832                                 new_item_len = length-1;
833                         }
834                                 ms = proto_tree_add_text(pres_tree_pc, tvb, *offset-1, 
835 new_item_len+(asn->offset-*offset)+1,
836                                                                                 val_to_str(type, presentation_context_definition_vals,
837                                                                                 "Unknown item (0x%02x)"));
838                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
839                                 *offset = asn->offset;
840
841
842                         switch(type)
843                                 {
844
845                         case SEQUENCE:
846                         show_fully_encoded_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
847                         *offset = old_offset+(new_item_len+header_len);
848                                         break;
849
850                         default:
851                                         proto_tree_add_text(pres_tree_ms, tvb, *offset, 
852 new_item_len+(asn->offset-*offset),
853                                         "Unknown asn.1 parameter: (0x%02x)", type);
854                                         *offset = old_offset+(new_item_len+header_len);
855                                 }
856                                 item_len = item_len -  (new_item_len+header_len);
857
858                         }
859
860
861                                         /*   align the pointer */
862                                         (*offset)=start+item_length;
863                                         asn->offset = (*offset);
864 }
865 static void
866 show_session_provider_abort(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t 
867 *tvb,int *offset,int item_len)
868 {
869         gint length;
870         gint            value;
871     proto_tree *pres_tree_pc = NULL;
872     proto_tree *pres_tree_pp = NULL;
873         proto_item *itu;
874         gint   new_item_len;
875
876
877 /* do we have enough bytes to dissect this item ? */
878                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
879                         {
880                                         proto_tree_add_text(pres_tree, tvb, *offset, item_len,
881                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
882                                                         *offset = asn->offset;
883                                                         return;
884                         }
885                         itu = proto_tree_add_text(pres_tree, tvb, *offset,item_len,
886                                         "Provider abort");
887                         pres_tree_pp = proto_item_add_subtree(itu, ett_pres_ms);
888
889                         if(item_len <= 0)
890                         {
891                                         proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
892                                                         "Provider reason not specified");
893                                                         *offset = asn->offset;
894                                                         return;
895                         }
896                         itu = proto_tree_add_text(pres_tree_pp, tvb, *offset,ABORT_REASON_LEN,
897                                         "Abort reason");
898                         pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
899                         (*offset)++; /* skip type  */
900                         asn->offset =  *offset;
901                         item_len--;
902                         /* get length  */
903                                 if (read_length(asn, pres_tree_pc, 0, &new_item_len) != 
904 ASN1_ERR_NOERROR)
905                                 {
906                                                         *offset = asn->offset;
907                                                         return;
908                                 }
909                         /*  try to get Abort reason  */
910                         value   =       get_integer_value(asn,new_item_len,offset);
911
912
913                         proto_tree_add_text(pres_tree_pc, tvb, *offset+1,new_item_len,
914                                         val_to_str(value, provider_abort_values_vals,"Unknown item (0x%02x)"));
915                         item_len-=(asn->offset-*offset)+new_item_len;
916                         *offset = asn->offset+new_item_len;
917                         asn->offset = *offset;
918                         /*  do we have Event identifier  ?  */
919                         if(item_len > 0)
920                         {
921                         itu = proto_tree_add_text(pres_tree_pp, tvb, *offset,item_len,
922                                         "Event identifier");
923                         pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
924
925                         (*offset)++; /* skip type  */
926                         asn->offset = *offset;
927                         item_len--;
928                         /* get length  */
929                                 if (read_length(asn, pres_tree_pc, 0, &new_item_len) != 
930 ASN1_ERR_NOERROR)
931                                 {
932                                                         *offset = asn->offset;
933                                                         return;
934                                 }
935                         /*  try to get Event identifier  */
936                         value   =       get_integer_value(asn,new_item_len,offset);
937
938                         proto_tree_add_text(pres_tree_pc, tvb, *offset+1,new_item_len,
939                                         val_to_str(value, event_identifier_values_vals,"Unknown item (0x%02x)"));
940                         item_len-=(asn->offset-*offset)+new_item_len;
941                         *offset = asn->offset+new_item_len;
942                                                 asn->offset = *offset;
943                         }
944 }
945 static void
946 show_user_data(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int 
947 *offset,int item_len,int tag)
948 {
949           proto_tree *pres_tree_ud = NULL;
950           proto_tree *pres_tree_pc = NULL;
951           proto_item *itm;
952           proto_item *itu;
953           guint   start = asn->offset;
954           guint   item_length = item_len;
955
956                         itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+ 
957 item_len,       "User data");
958                         pres_tree_ud = proto_item_add_subtree(itm, ett_pres_ms);
959                         itu = proto_tree_add_text(pres_tree_ud, tvb, 
960 *offset,item_len+(asn->offset-*offset),
961                                         val_to_str(tag, user_data_values_vals,"Unknown item (0x%02x)"));
962                         pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
963                         switch(tag)
964                         {
965                         case SIMPLY_ENCODED_DATA:
966                                 break;
967                         case FULLY_ENCODED_DATA:
968                                 show_fully_encoded_data(asn,pres_tree_pc,tvb,offset,item_len);
969                                 break;
970                         default:
971                                 break;
972                         }
973
974
975                         /*   align the pointer */
976                         (*offset)=start+item_length;
977                         asn->offset = (*offset);
978
979 }
980
981 static void
982 show_presentation_context_definition(ASN1_SCK *asn,proto_tree 
983 *pres_tree,tvbuff_t *tvb,int *offset,int item_len,int tag)
984 {
985           proto_tree *pres_tree_ms = NULL;
986           proto_tree *pres_tree_pc = NULL;
987           proto_item *itm;
988           gint    length;
989           guint   type;
990           guint   header_len;
991           proto_item *ms;
992           gint   new_item_len;
993           guint   start = asn->offset;
994           guint   item_length = item_len;
995
996                         itm = proto_tree_add_text(pres_tree, tvb, 
997 *offset,item_len+(asn->offset-*offset),
998                                         val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
999                         pres_tree_pc = proto_item_add_subtree(itm, ett_pres_ms);
1000
1001 /* do we have enough bytes to dissect ? */
1002                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
1003                         {
1004                                         proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
1005                                                         "Wrong item.Need %u bytes but have %u", item_len,length);
1006                                         /*   align the pointer */
1007                                         (*offset)=start+item_length;
1008                                         asn->offset = (*offset);
1009                                         return ;
1010                         }
1011                         *offset =asn->offset;
1012                         start = *offset;
1013                         /*  read the rest */
1014                         while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
1015                         {
1016                                 int old_offset = *offset;
1017                         /*  get item type  */
1018                         type = tvb_get_guint8(tvb, *offset);
1019                         /* skip type */
1020                         (*offset)++;
1021                         asn->offset = *offset;
1022                         /* get length  */
1023                                 if (read_length(asn, pres_tree_pc, 0, &new_item_len) != 
1024 ASN1_ERR_NOERROR)
1025                                 {
1026                                         /*   align the pointer */
1027                                         (*offset)=start+item_length;
1028                                         asn->offset = (*offset);
1029                                         return  ;
1030                                 }
1031                                 header_len = asn->offset - (*offset) +1;
1032                         /* do we have enough bytes to dissect ? */
1033                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < 
1034 new_item_len )
1035                         {
1036                                         proto_tree_add_text(pres_tree_pc, tvb, *offset, new_item_len,
1037                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
1038                                         /*   align the pointer */
1039                                         (*offset)=start+item_length;
1040                                         asn->offset = (*offset);
1041                                         return ;
1042                         }
1043                                 ms = proto_tree_add_text(pres_tree_pc, tvb, *offset-1, 
1044 new_item_len+(asn->offset-*offset)+1,
1045                                                                                 val_to_str(type, presentation_context_definition_vals,
1046                                                                                 "Unknown item (0x%02x)"));
1047                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1048                                 *offset = asn->offset;
1049
1050
1051                         switch(type)
1052                                 {
1053
1054                         case SEQUENCE:
1055                                 if(tag == PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST
1056                                         || tag == DEFAULT_CONTEXT_RESULT)
1057                                 {
1058                         show_presentation_context_definition_result_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
1059                                 }
1060                                 else
1061                                 {
1062                         show_presentation_context_definition_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
1063                                 }
1064                         *offset = old_offset+(new_item_len+header_len);
1065                                         break;
1066
1067                         default:
1068                                         proto_tree_add_text(pres_tree_ms, tvb, *offset, 
1069 new_item_len+(asn->offset-*offset),
1070                                         "Unknown asn.1 parameter: (0x%02x)", type);
1071                                         *offset = old_offset+(new_item_len+header_len);
1072                                 }
1073                                 item_len = item_len -  (new_item_len+header_len);
1074
1075                         }
1076
1077
1078                                         /*   align the pointer */
1079                                         (*offset)=start+item_length;
1080                                         asn->offset = (*offset);
1081 }
1082 /* if we can't dissect */
1083 static void
1084 dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
1085                     proto_tree *tree, const char *field_name, int ret)
1086 {
1087         char *errstr;
1088         errstr = asn1_err_to_str(ret);
1089
1090         if (tree != NULL)
1091         {
1092                 proto_tree_add_text(tree, tvb, offset, 0,
1093                     "ERROR: Couldn't parse %s: %s", field_name, errstr);
1094                 call_dissector(data_handle,
1095                     tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
1096         }
1097 }
1098
1099 static int read_string_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
1100         proto_item **new_item, char **s, int start, guint length)
1101 {
1102   guchar *string;
1103   proto_item *temp_item = NULL;
1104   int ret;
1105
1106   if (length)
1107   {
1108     ret = asn1_string_value_decode(a, length, &string);
1109     if (ret != ASN1_ERR_NOERROR)
1110         {
1111       if (tree)
1112           {
1113         proto_tree_add_text(tree, a->tvb, start, 0,
1114           "%s: ERROR: Couldn't parse value: %s",
1115           proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
1116       }
1117       return ret;
1118     }
1119     string = g_realloc(string, length + 1);
1120     string[length] = '\0';
1121   }
1122   else
1123     string = "(null)";
1124
1125   if (hf_id)
1126     temp_item = proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset 
1127 - start, string);
1128   if (new_item)
1129     *new_item = temp_item;
1130
1131   if (s && length)
1132     *s = string;
1133   else
1134           if (length)
1135                         g_free(string);
1136   return ASN1_ERR_NOERROR;
1137 }
1138 static void
1139 show_provider_reason(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int 
1140 *offset,int item_len,int type)
1141 {
1142           proto_item *ms;
1143           proto_item *pr;
1144           proto_tree *pres_tree_ms = NULL;
1145           proto_tree *pres_tree_pr = NULL;
1146           int           off      = *offset;
1147           int           value=0;
1148           int           new_item_len = item_len+(asn->offset-*offset);
1149
1150                                 ms = proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
1151                                                                                 val_to_str(type, sequence_top_vals,
1152                                                                                 "Unknown item (0x%02x)"));
1153                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1154                                 value   =       get_integer_value(asn,item_len,offset);
1155                                 pr = proto_tree_add_text(pres_tree_ms, tvb, *offset, new_item_len,
1156                                                                                 val_to_str(value, provider_reason_values_vals,
1157                                                                                 "Unknown item (0x%02x)"));
1158                                 pres_tree_pr = proto_item_add_subtree(pr, ett_pres_ms);
1159                                 print_value(asn,pres_tree_pr,tvb,offset,item_len);
1160                                 asn->offset = *offset = off+new_item_len;
1161 }
1162 static void
1163 show_presentation_selector (ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t 
1164 *tvb,int *offset,int item_len,int type)
1165 {
1166           proto_item *ms;
1167           proto_tree *pres_tree_ms = NULL;
1168           int ret;
1169           char *s;
1170
1171                                 ms = proto_tree_add_text(pres_tree, tvb, *offset, 
1172 item_len+(asn->offset-*offset),
1173                                                                                 val_to_str(type, sequence_top_vals,
1174                                                                                 "Unknown item (0x%02x)"));
1175
1176
1177                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1178
1179                                 ret = read_string_value(asn, pres_tree,0,NULL, &s, 
1180 *offset+(asn->offset-*offset), item_len);
1181                                 if(ret == ASN1_ERR_NOERROR)
1182                                 {
1183                                         if( item_len)
1184                                         {
1185                                                         proto_tree_add_text(pres_tree_ms, tvb, *offset+2, item_len,
1186                                                                                         "String:%s",s);
1187                                                         g_free(s);
1188                                         }
1189                                         else
1190                                         {
1191                                                         proto_tree_add_text(pres_tree_ms, tvb, *offset+2, item_len,
1192                                                                                         "Zero selector length");
1193
1194                                         }
1195                                 }
1196
1197
1198
1199 }
1200 /* display top sequence  */
1201 static void
1202 show_sequence_top(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t 
1203 *tvb,packet_info *pinfo,int *offset,int item_len)
1204 {
1205         int ret;
1206         guint cls, con, tag,len1;
1207         gint  type;
1208         gboolean def;
1209         proto_item *itm;
1210         gint length;
1211         while(item_len > 0 )
1212         {
1213 /* do we have enough bytes to dissect this item ? */
1214                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
1215                         {
1216                                         proto_tree_add_text(pres_tree, tvb, *offset, item_len,
1217                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
1218                                         break;
1219                         }
1220                 /*   get  tag     */
1221                         type = tvb_get_guint8(tvb, *offset);
1222                 /* decode header  */
1223                         ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
1224
1225                         if (ret != ASN1_ERR_NOERROR)
1226                         {
1227                                                         dissect_parse_error(tvb, *offset, pinfo, pres_tree,
1228                                                                         "sequence error", ret);
1229                                 break;
1230                         }
1231                         item_len = item_len - (asn->offset - *offset);
1232                                                 /*
1233                                                 * [APPLICATION <tag>]
1234                                                 */
1235                                                 switch (tag)
1236                                                         {
1237                                                                 case TAG_01:
1238                                                                         /* Calling-presentation-selector and
1239                                                                            User data have the same tag number
1240                                                                            Try to recognize which one do we really have */
1241                                                                         if( con == ASN1_CON)
1242                                                                         {
1243                                                                                 /* it is User data */
1244                                                                                 /* print it                 */
1245                                                                                 show_user_data(asn,pres_tree,tvb,offset,len1,type);
1246                                                                                 break;
1247                                                                         }
1248                                                                         /*  it is Calling-presentation-selector  */
1249                                                                         /*  simply go below, we don't need to break here */
1250
1251                                                                 case CALLED_PRESENTATION_SELECTOR:
1252                                                                 case RESPONDING_PRESENTATION_SELECTOR:
1253                                                                 /*case CALLING_PRESENTATION_SELECTOR:*/
1254                                                                 /*
1255                                                                 * [Called-presentation-selector]
1256                                                                 * [Calling-presentation-selector]
1257                                                                 * [Responding-presentation-selector]
1258                                                                 */
1259                                                                         show_presentation_selector(asn,pres_tree,tvb,offset,len1,tag);
1260                                                                         break;
1261                                                                 case DEFAULT_CONTEXT_NAME:
1262                                                                 case PRESENTATION_CONTEXT_DEFINITION_LIST:
1263                                                                         show_presentation_context_definition(asn,pres_tree,tvb,offset,len1,tag);
1264                                                                         break;
1265                                                                 case PROTOCOL_VERSION:
1266                                                                 /*case TAG_00:  */
1267                                                                         if(cls == ASN1_APL)
1268                                                                         {
1269                                                                                 /* yes, it is application */
1270                                                                                          *offset = asn->offset;
1271                                                                                         item_len = len1;
1272                                                                                         continue;
1273                                                                         }
1274                                                                         show_protocol_version(asn,pres_tree,tvb,offset,len1,tag);
1275                                                                         break;
1276                                                                 case PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST:
1277                                                                 case DEFAULT_CONTEXT_RESULT:
1278                                                                         show_presentation_context_definition(asn,pres_tree,tvb,offset,len1,tag);
1279                                                                         break;
1280                                                                 case PRESENTATION_REQUIREMENTS:
1281                                                                         show_presentation_requirements(asn,pres_tree,tvb,offset,len1,tag);
1282                                                                         break;
1283                                                                 case PROVIDER_REASON:
1284                                                                         show_provider_reason(asn,pres_tree,tvb,offset,len1,tag);
1285                                                                         break;
1286                                                                 /* to do */
1287
1288                                                                 case USER_SESSION_REQUIREMENTS:
1289
1290                                                                         itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset 
1291 -*offset)+ len1,
1292                                                                                         val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
1293                                                                 (asn->offset)+=len1;
1294                                                                         break;
1295
1296                                                                 default:
1297                                                                         itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset 
1298 -*offset)+ len1,
1299                                                                                         "Unknown tag: %x",tag);
1300                                                                         (asn->offset)+=len1;
1301                                                         }
1302
1303                 item_len-=len1;
1304                 *offset = asn->offset;
1305         }
1306
1307 }
1308 static void
1309 show_connection_request_confirm(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t 
1310 *tvb,packet_info *pinfo,int *offset,int* item_len)
1311 {
1312   guint8 type;
1313   guint length;
1314   proto_tree *pres_tree_ms = NULL;
1315   proto_item *ms;
1316                         /*  get type of set  */
1317                         while ( tvb_reported_length_remaining(tvb, *offset) > 0 )
1318                         {
1319                                 int asn1_tag;
1320                         /*  get item type  */
1321                         type = tvb_get_guint8(tvb, *offset);
1322                         asn1_tag = type & 0x1f;
1323                         /* skip type */
1324                         (*offset)++;
1325                         asn->offset = *offset;
1326                         /* get length  */
1327                                 if (read_length(asn, pres_tree, 0, item_len) != ASN1_ERR_NOERROR)
1328                                 {
1329                                         return;
1330                                 }
1331                         /* do we have enough bytes to dissect ? */
1332                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < 
1333 (guint)*item_len )
1334                         {
1335                                         proto_tree_add_text(pres_tree, tvb, *offset, -1,
1336                                                         "Wrong item.Need %u bytes but have %u", *item_len,length);
1337                                 return;
1338                         }
1339                                 ms = proto_tree_add_text(pres_tree, tvb, *offset-1, 
1340 *item_len+(asn->offset-*offset)+1,
1341                                                                                 val_to_str(asn1_tag, cr_vals,
1342                                                                                 "Unknown item (0x%02x)"));
1343                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1344
1345                         switch(asn1_tag)
1346                                 {
1347                         case MODE_SELECTOR:
1348                                 proto_tree_add_uint(pres_tree_ms, hf_pres_ms_type, tvb, (*offset)-1, 1, 
1349 type);
1350                                 proto_tree_add_text(pres_tree_ms, tvb, *offset, (asn->offset-*offset),
1351                                                                                 "Length:%u",*item_len);
1352                                 *offset=asn->offset;
1353                                 show_integer(asn,pres_tree_ms,tvb,offset,*item_len);
1354                                         break;
1355                         case SET_TOP:
1356                         case SEQUENCE_TOP:
1357                                 proto_tree_add_uint(pres_tree_ms, hf_pres_seq_type, tvb, (*offset)-1, 1, 
1358 type);
1359                                 proto_tree_add_text(pres_tree_ms, tvb, *offset, (asn->offset-*offset),
1360                                                                                 "Length:%u",*item_len);
1361                                 *offset=asn->offset;
1362                                 show_sequence_top(asn,pres_tree_ms,tvb,pinfo,offset,*item_len);
1363                                         break;
1364                         default:
1365                                         proto_tree_add_text(pres_tree, tvb, (*offset)-1, 
1366 *item_len+(asn->offset-*offset)+1,
1367                                         "Unknown asn.1 parameter: (0x%02x).Tag :(0x%02x)", type,asn1_tag);
1368                                         (*offset)+=*item_len+(asn->offset-*offset);
1369                                         asn->offset = *offset;
1370                                 }
1371
1372                         }
1373 }
1374
1375
1376 /*
1377 * Dissect an Ppdu.
1378 */
1379 static int
1380 dissect_ppdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree 
1381 *tree)
1382 {
1383   proto_item *ti;
1384   proto_tree *pres_tree = NULL;
1385   guint length;
1386   guint       rest_len;
1387   guint  s_type;
1388   ASN1_SCK asn;
1389   guint cp_type_len;
1390 /* do we have spdu type from the session dissector?  */
1391         if( !pinfo->private_data )
1392                                 {
1393                                 if(tree)
1394                                                 {
1395                                         proto_tree_add_text(tree, tvb, offset, -1,
1396                                                         "Internal error:can't get spdu type from session dissector.");
1397                                         return  FALSE;
1398                                                 }
1399                                 }
1400         else
1401                                 {
1402                                         session  = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
1403                                         if(session->spdu_type == 0 )
1404                                         {
1405                                                 if(tree)
1406                                                 {
1407                                         proto_tree_add_text(tree, tvb, offset, -1,
1408                                                         "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
1409                                         return  FALSE;
1410                                                 }
1411                                         }
1412                                 }
1413 /* get type of tag      */
1414         s_type = tvb_get_guint8(tvb, offset);
1415                 /*  set up type of Ppdu */
1416         if (check_col(pinfo->cinfo, COL_INFO))
1417                                         col_add_str(pinfo->cinfo, COL_INFO,
1418                                                 val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
1419   if (tree)
1420         {
1421                 ti = proto_tree_add_item(tree, proto_pres, tvb, offset, -1,
1422                     FALSE);
1423                 pres_tree = proto_item_add_subtree(ti, ett_pres);
1424         }
1425         offset++;
1426 /*    open asn.1 stream    */
1427         asn1_open(&asn, tvb, offset);
1428
1429         switch(session->spdu_type)
1430         {
1431                 case SES_REFUSE:
1432                         proto_tree_add_uint(pres_tree, hf_pres_type, tvb, offset-1, 1, s_type);
1433                 if (read_length(&asn, pres_tree, hf_cp_type_message_length, &cp_type_len) 
1434 != ASN1_ERR_NOERROR)
1435                                         {
1436                                         return  FALSE;
1437                                         }
1438                         /* skip length   */
1439                         offset = asn.offset;
1440                         /* do we have enough bytes to dissect ? */
1441                         if( ( length =tvb_reported_length_remaining(tvb, offset))  < cp_type_len 
1442 )
1443                         {
1444                                 if(tree)
1445                                 {
1446                                         proto_tree_add_text(pres_tree, tvb, offset, -1,
1447                                                         "Wrong Ppdu.Need %u bytes but have %u", cp_type_len,length);
1448                                 }
1449                         return FALSE;
1450                         }
1451                                 {
1452                                 asn.offset = offset;
1453                                 show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,cp_type_len);
1454                                 offset=asn.offset;
1455                                 }
1456                         break;
1457                 case SES_CONNECTION_REQUEST:
1458                 case SES_CONNECTION_ACCEPT:
1459                         proto_tree_add_uint(pres_tree, hf_pres_type, tvb, offset-1, 1, s_type);
1460
1461                         if (read_length(&asn, pres_tree, hf_cp_type_message_length, &cp_type_len) 
1462 != ASN1_ERR_NOERROR)
1463                                         {
1464                                         return  FALSE;
1465                                         }
1466                         /* skip length   */
1467                         offset = asn.offset;
1468                         /* do we have enough bytes to dissect ? */
1469                         if( ( length =tvb_reported_length_remaining(tvb, offset))  < cp_type_len 
1470 )
1471                         {
1472                                 if(tree)
1473                                 {
1474                                         proto_tree_add_text(pres_tree, tvb, offset, -1,
1475                                                         "Wrong Ppdu.Need %u bytes but have %u", cp_type_len,length);
1476                                 }
1477                         return FALSE;
1478                         }
1479                         {
1480                         show_connection_request_confirm(&asn,pres_tree,tvb,pinfo,&offset,&cp_type_len);
1481                         }
1482                                 break;
1483                 case SES_ABORT:
1484                                 /* get length  */
1485                                 if (read_length(&asn, pres_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1486                                                 {
1487                                         return  FALSE;
1488                                                 }
1489                                 /* skip length   */
1490                                 offset = asn.offset;
1491                                 /* do we have enough bytes to dissect ? */
1492                                 if( ( length =tvb_reported_length_remaining(tvb, offset))  < rest_len )
1493                                 {
1494                                         if(tree)
1495                                         {
1496                                         proto_tree_add_text(pres_tree, tvb, offset, -1,
1497                                                         "Wrong Ppdu.Need %u bytes but have %u", rest_len,length);
1498                                         }
1499                                 return FALSE;
1500                                 }
1501                                 if(session->abort_type == SESSION_USER_ABORT )
1502                                 {
1503                                         /* is it PC */
1504                                         if(s_type == ASN1_CLASS_PC+ASN1_CLASS_CONTEXT_SPECIFIC)
1505                                         {
1506                                                         {
1507                                                         offset=asn.offset;
1508                                                         show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,rest_len);
1509                                                         offset=asn.offset;
1510                                                         }
1511                                         }
1512                                         else
1513                                         {
1514                                                         {
1515                                                         offset=asn.offset;
1516                                                         show_session_provider_abort(&asn,pres_tree,tvb,&offset,rest_len);
1517                                                         offset=asn.offset;
1518                                                         }
1519                                         }
1520                                 }
1521                                 else
1522                                 {
1523                                                         {
1524                                                         offset=asn.offset;
1525                                                         show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,rest_len);
1526                                                         offset=asn.offset;
1527                                                         }
1528                                 }
1529                         break;
1530                 default:
1531                         {
1532                                 proto_item *ms;
1533                                 proto_tree *pres_tree_ms = NULL;
1534                                 /* back to length  */
1535                                   offset--;
1536                                 /* get length  */
1537                                 if (read_length(&asn, pres_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1538                                                 {
1539                                         return  FALSE;
1540                                                 }
1541                                 if(!rest_len)
1542                                 {
1543                                         guint       rest_pdu_len = 0;
1544                                         /* do we really haven't any more bytes ? */
1545                                         if(     (rest_pdu_len = tvb_reported_length_remaining(tvb, offset)) )
1546                                         {
1547                                                 /*
1548                                                  * we have but can't say how many from asn1 information.
1549                                                  * use pdu len instead
1550                                                  */
1551                                                 if(rest_pdu_len > 2)
1552                                                 {
1553                                                 rest_len = rest_pdu_len;
1554                                                 }
1555                                         }
1556                                 }
1557                 if( ((gint)rest_len) > 0) {
1558                                 ms = proto_tree_add_text(pres_tree, tvb, offset, rest_len,
1559                                                                                 val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
1560                                 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1561                                 show_user_data(&asn,pres_tree_ms,tvb,&offset,rest_len,s_type);
1562                 }
1563                         }
1564         }
1565 /*    close asn.1 stream    */
1566           asn1_close(&asn, &offset);
1567
1568         return offset;
1569 }
1570
1571 /*
1572 * Dissect PPDUs inside a SPDU.
1573 */
1574 static void
1575 dissect_pres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1576 {
1577         int offset = 0;
1578 /* first, try to check length   */
1579 /* do we have at least 4 bytes  */
1580         if (!tvb_bytes_exist(tvb, 0, 4))
1581         {
1582                         proto_tree_add_text(tree, tvb, offset, tvb_reported_length_remaining(tvb, 
1583 offset),
1584                                                                 "User data");
1585                         return;  /* no, it isn't a presentation PDU */
1586         }
1587
1588         /*  we can't make any additional checking here   */
1589         /*  postpone it before dissector will have more information */
1590
1591         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1592                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRES");
1593         if (check_col(pinfo->cinfo, COL_INFO))
1594                 col_clear(pinfo->cinfo, COL_INFO);
1595         /* save pointers for calling the acse dissector  */
1596         global_tree = tree;
1597         global_pinfo = pinfo;
1598
1599         while (tvb_reported_length_remaining(tvb, offset) > 0)
1600                         {
1601                 offset = dissect_ppdu(tvb, offset, pinfo, tree);
1602                 if(offset == FALSE )
1603                                                         {
1604                                                                         proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
1605                                                                         offset = tvb_length(tvb);
1606                                                                         break;
1607                                                         }
1608                         }
1609 }
1610
1611 void
1612 proto_register_pres(void)
1613 {
1614         static hf_register_info hf[] =
1615         {
1616                 {
1617                         &hf_pres_type,
1618                         {
1619                                 "PPDU Type",
1620                                 "pres.type",
1621                                 FT_UINT8,
1622                                 BASE_DEC,
1623                                 VALS(pres_vals),
1624                                 0x0,
1625                                 "", HFILL
1626                         }
1627                 },
1628                 {
1629                         &hf_pres_length,
1630                         {
1631                                 "Length",
1632                                 "pres.length",
1633                                 FT_UINT16,
1634                                 BASE_DEC,
1635                                 NULL,
1636                                 0x0,
1637                                 "", HFILL
1638                         }
1639                 },
1640                 {
1641                         &hf_cp_type_message_length,
1642                         {
1643                                 "Message Length",
1644                                 "cp_type.message_length",
1645                                 FT_UINT32,
1646                                 BASE_DEC,
1647                                 NULL,
1648                                 0x0,
1649                                 "CP type Message Length",
1650                                 HFILL
1651                         }
1652                 },
1653                 {
1654                         &hf_pres_rc_type,
1655                         {
1656                                 "Connection reqiest/confirm",
1657                                 "pres.type",
1658                                 FT_UINT8,
1659                                 BASE_DEC,
1660                                 VALS(pres_vals),
1661                                 0x0,
1662                                 "Connection reqiest/confirm",
1663                                 HFILL
1664                         }
1665                 },
1666
1667                 {
1668                         &hf_pres_ms_type,
1669                         {
1670                                 "Mode selector",
1671                                 "pres.mode.selector",
1672                                 FT_UINT8,
1673                                 BASE_DEC,
1674                                 NULL,
1675                                 0x0,
1676                                 "Mode select",
1677                                 HFILL
1678                         }
1679                 },
1680                 {
1681                         &hf_pres_protocol_version,
1682                         {
1683                                 "Protocol version",
1684                                 "pres.protocol.version",
1685                                 FT_UINT16,
1686                                 BASE_HEX,
1687                                 NULL,
1688                                 0x0,
1689                                 "Protocol version",
1690                                 HFILL
1691                         }
1692                 },
1693                 {
1694                         &hf_value,
1695                         {
1696                                 "Value",
1697                                 "pres.value",
1698                                 FT_UINT8,
1699                                 BASE_DEC,
1700                                 NULL,
1701                                 0x0,
1702                                 "Value",
1703                                 HFILL
1704                         }
1705                 },
1706
1707                 {
1708                         &hf_pres_seq_type,
1709                         {
1710                                 "Sequence",
1711                                 "pres.sequence",
1712                                 FT_UINT8,
1713                                 BASE_DEC,
1714                                 NULL,
1715                                 0x0,
1716                                 "Mode select",
1717                                 HFILL
1718                         }
1719                 },
1720
1721                 {
1722                         &hf_protocol_version,
1723                         {
1724                                 "Protocol version 1",
1725                                 "pres.protocol.version",
1726                                 FT_BOOLEAN, 16,
1727                                 NULL,
1728                                 PRES_PROTOCOL_VERGION,
1729                                 "Protocol version 1",
1730                                 HFILL
1731                         }
1732                 },
1733                 {
1734                         &hf_context_management,
1735                         {
1736                                 "Context management",
1737                                 "pres.context.management",
1738                                 FT_BOOLEAN, 16,
1739                                 NULL,
1740                                 PRES_CONTEXT_MANAGEMENT,
1741                                 "Context management",
1742                                 HFILL
1743                         }
1744                 },
1745                 {
1746                         &hf_restoration,
1747                         {
1748                                 "Restoration",
1749                                 "pres.restoration",
1750                                 FT_BOOLEAN, 16,
1751                                 NULL,
1752                                 PRES_RESTORATION,
1753                                 "Restoration",
1754                                 HFILL
1755                         }
1756                 },
1757
1758
1759         };
1760
1761         static gint *ett[] =
1762         {
1763                 &ett_pres,
1764                 &ett_pres_param,
1765                 &ett_pres_rc,
1766                 &ett_pres_ms,
1767                 &ett_pres_itm,
1768         };
1769         module_t *pres_module;
1770
1771
1772         proto_pres = proto_register_protocol(PROTO_STRING_PRES, "PRES", "pres");
1773         proto_register_field_array(proto_pres, hf, array_length(hf));
1774         proto_register_subtree_array(ett, array_length(ett));
1775
1776         pres_module = prefs_register_protocol(proto_pres, NULL);
1777
1778         /*
1779          * Register the dissector by name, so other dissectors can
1780          * grab it by name rather than just referring to it directly
1781          * (you can't refer to it directly from a plugin dissector
1782          * on Windows without stuffing it into the Big Transfer Vector).
1783          */
1784         register_dissector("pres", dissect_pres, proto_pres);
1785 }
1786
1787 void
1788 proto_reg_handoff_pres(void)
1789 {
1790         /*   find data dissector  */
1791         data_handle = find_dissector("data");
1792         /* define acse sub dissector */
1793         acse_handle = find_dissector("acse");
1794 }