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