Set the svn:eol-style property on all text files to "native", so that
[obnox/wireshark/wip.git] / packet-acse.c
1 /* packet-acse.c
2 *
3 * Routine to dissect OSI ACSE 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-acse.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 /* acse header fields             */
51 static int proto_acse          = -1;
52 /*   type of session envelop */
53 static struct SESSION_DATA_STRUCTURE* session = NULL;
54 /* acse fields defining a sub tree */
55 static gint ett_acse           = -1;
56 static gint ett_acse_param     = -1;
57 static gint ett_acse_rc           = -1;
58 static gint ett_acse_ms           = -1;
59 static gint ett_acse_itm           = -1;
60
61 /*
62 ----------------------------------------------------------------------------------------------------------*/
63 /* Subdissector tables */ 
64 static dissector_table_t application_dissector_table; 
65 static dissector_handle_t app_handle = NULL;
66 static int hf_acse_type        = -1;
67 static int hf_cp_type_message_length = -1;
68 static int hf_protocol_version       = -1;
69
70
71
72 static const value_string acse_vals[] =
73 {
74   {ACSE_AARQ,  "A-associate request" },
75   {ACSE_AARE,  "A-associate response" },
76   {ACSE_RLRQ,  "A-reliase request" },
77   {ACSE_RLRE,  "A-reliase response" },
78   {ACSE_ABRT,  "A-abort" },
79   {0,             NULL           }
80 };
81
82 static const value_string cr_vals[] =
83 {
84   {MODE_SELECTOR, "Mode Selector"},
85   {SEQUENCE_TOP, "Sequence"},
86   {SET_TOP, "Set"},
87   {0, NULL}
88 };
89
90 static const value_string request_sequence_top_vals[] =
91 {
92   {PROTOCOL_VERSION, "Protocol version"},
93   {APPLICATION_CONTEXT_NAME, "Application context name"},
94   {CALLED_AP_TITLE, "Called AP title"},
95   {CALLED_AE_QUALIFIER, "Called AE qualifier"},
96   {CALLED_AP_INVOKATION_ID, "Called AP invokation id"},
97   {CALLED_AE_INVOKATION_ID, "Called AE invokation id"},
98   {CALLING_AP_TITLE, "Calling AP title"},
99   {CALLING_AE_QUALIFIER, "Calling AE qualifier"},
100   {CALLING_AP_INVOKATION_ID, "Calling AP invokation id"},
101   {CALLING_AE_INVOKATION_ID, "Calling AE invokation id"},
102   {IMPLEMENTATION_INFORMATION,"Implementation information"},
103   {USER_INFORMATION,"User information"},
104   {0, NULL}
105 };
106 static const value_string response_sequence_top_vals[] =
107 {
108   {PROTOCOL_VERSION, "Protocol version"},
109   {APPLICATION_CONTEXT_NAME, "Application context name"},
110   {ACSE_RESULT, "Result"},
111   {ACSE_RESULT_SOURCE_DIAGNOSTIC, "Result source diagnostic"},
112   {RESPONDING_AP_TITLE, "Responding AP title"},
113   {RESPONDING_AE_QUALIFIER, "Responding AE qualifier"},
114   {RESPONDING_AP_INVOKATION_ID, "Responding AP invokation id"},
115   {RESPONDING_AE_INVOKATION_ID, "Responding AE invokation id"},
116   {IMPLEMENTATION_INFORMATION,"Implementation information"},
117   {USER_INFORMATION,"User information"},
118   {0, NULL}
119 };
120 static const value_string associate_result_values_vals[] =
121 {
122   {PRESENTATION_RESULT_ACCEPTANCE,"Accepted"},
123   {PRESENTATION_RESULT_USER_REJECTION,"Rejected permanent"},
124   {PRESENTATION_RESULT_PROVIDER_REJECTION,"Rejected transient"},
125   {0, NULL}
126 };
127
128 static const value_string acse_associate_source_diagnostic_vals[] =
129 {
130   {ACSE_SERVICE_USER,"Acse service user"},
131   {ACSE_SERVICE_PROVIDER,"Acse service provider"},
132   {0, NULL}
133 };
134 static const value_string acse_service_user_values_vals[] =
135 {
136   {ACSE_NULL,"null"},
137   {ACSE_NO_REASON_GIVEN,"No reason given"},
138   {ACSE_APPLICATION_CONTEXT_NAME_NOT_SUPPORTED,"Application context name not supported"},
139   {ACSE_CALLING_AP_TITLE_NOT_RECOGNIZED,"Calling AP title not recognized"},
140   {ACSE_CALLING_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Calling AP invokation identifier not recognized"},
141   {ACSE_CALLING_AE_QUALIFIER_NOT_RECOGNIZED,"Calling AE qualifier not recognized"},
142   {ACSE_CALLING_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Calling AE invokation identifier not recognized"},
143   {ACSE_CALLED_AP_TITLE_NOT_RECOGNIZED,"Called AP title not recognized"},
144   {ACSE_CALLED_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Called AP invokation identifier not recognized"},
145   {ACSE_CALLED_AE_QUALIFIER_NOT_RECOGNIZED,"Called AE qualifier not recognized"},
146   {ACSE_CALLED_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Called AE invokation identifier not recognized"},
147   {0, NULL}
148 };
149 static const value_string acse_service_provider_values_vals[] =
150 {
151   {ACSE_NULL,"Null"},
152   {ACSE_NO_REASON_GIVEN,"No reason given"},
153   {ACSE_NO_COMMON_ACSE_VERSION,"no_common_acse_version"},
154   {0, NULL}
155 };
156
157 static const value_string acse_user_information_vals[] =
158 {
159   {ACSE_EXTERNAL_USER,"External"},
160   {0, NULL}
161 };
162 static const value_string sequence_list_vals[] =
163 {
164   {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
165   {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
166   {TRANSFER_SYNTAX_NAMES,"Transfer syntax names"},
167   {0, NULL}
168 };
169 static const value_string presentation_context_definition_vals[] =
170 {
171   {SEQUENCE, "Sequence"},
172   {0, NULL}
173 };
174 static const value_string user_data_values_vals[] =
175 {
176   {SIMPLY_ENCODED_DATA,"Simply encoded data"},
177   {FULLY_ENCODED_DATA,"Fully encoded data "},
178   {0, NULL}
179 };
180 static const value_string presentation_data_values[] =
181 {
182   {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
183   {SINGLE_ASN1_TYPE,"Single ASN.1 type"},
184   {OCTET_ALIGNED,"Octet aligned"},
185   {ARBITRARY,"Arbitrary"},
186   {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
187   {0, NULL}
188 };
189 static const value_string release_request_reason[] =
190 {
191   {RRR_NORMAL,"Normal"},
192   {RRR_URGENT,"Urgent"},
193   {RRR_USER_DEFINED,"User defined"},
194   {0, NULL}
195 };
196 static const value_string release_response_reason[] =
197 {
198   {RRPR_NORMAL,"Normal"},
199   {RRPR_URGENT,"Not finished"},
200   {RRPR_USER_DEFINED,"User defined"},
201   {0, NULL}
202 };
203
204 static const value_string abort_reason[] =
205 {
206   {ABRT_ACSE_SERVICE_USER,"Acse service user"},
207   {ABRT_ACSE_SERVICE_PROVIDER,"Acse service provider"},
208   {0, NULL}
209 };
210
211 static const value_string type_app[] =
212 {
213         {0,""},             /*   for unknown dissector   */
214         {FTAM_APP,"FTAM"},
215         {CMIP_APP,"CMIP"},
216         {0, NULL}
217 };
218
219 /*      pointers for acse dissector  */
220 static proto_tree *global_tree  = NULL;
221 static packet_info *global_pinfo = NULL;
222 /* dissector for data */
223 static dissector_handle_t data_handle;
224 static void
225 call_app_dissector(tvbuff_t *tvb, gint offset, gint param_len,
226     packet_info *pinfo, proto_tree *tree, proto_tree *param_tree)
227 {
228         /* do we have OSI app packet dissector ? */
229         if(!app_handle )
230         {
231
232                 /* No - display as data */
233                 if (tree)
234                 {
235                         proto_tree_add_text(param_tree, tvb, offset, param_len,
236                             "dissector is not available");
237                 }
238         }
239         else
240         {
241                         /* Yes - call application dissector */
242                         tvbuff_t *next_tvb;
243
244                         next_tvb = tvb_new_subset(tvb, offset, param_len,
245                             param_len);
246                         TRY
247                         {
248                                 call_dissector(app_handle, next_tvb, pinfo,
249                                     tree);
250                         }
251                         CATCH_ALL
252                         {
253                                 show_exception(tvb, pinfo, tree, EXCEPT_CODE);
254                         }
255                         ENDTRY;
256         }
257 }
258 static char*
259 string_to_hex(const unsigned char * in,char * out,int len)
260 {
261         char ascii[MAXSTRING];
262         int  i;
263         memset(&ascii,0x00,sizeof(ascii));
264 for(i=0;i<len;i++)
265                         {
266         unsigned char o_out = *(in+i);
267     sprintf(out+(i<<1),"%.2x",*  (in+i));
268         if(  ( (o_out) >= 'a') & ( (o_out) <='z')  ||
269                  ( (o_out) >= 'A') & ( (o_out) <='Z')  ||
270                  ( (o_out) >= '0') & ( (o_out) <='9')
271            )
272                                         {
273                                         ascii[i] = o_out;
274                                         }
275                                 else
276                                         {
277                                         ascii[i] = '.';
278                                         }
279
280                         }
281                 strcat(out," ");
282                 strcat(out,ascii);
283     return out;
284 }
285
286 static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
287 {
288   guint length = 0;
289   gboolean def = FALSE;
290   int start = a->offset;
291   int ret;
292
293   ret = asn1_length_decode(a, &def, &length);
294   if (ret != ASN1_ERR_NOERROR)
295   {
296     if (tree)
297         {
298       proto_tree_add_text(tree, a->tvb, start, 0,
299         "%s: ERROR: Couldn't parse length: %s",
300         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
301     }
302     return ret;
303   }
304
305   if (len)
306     *len = length;
307
308   if (tree && hf_id)
309     proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start,
310 length);
311
312   return ASN1_ERR_NOERROR;
313 }
314 static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
315         proto_item **new_item, guint *i, int start, guint length)
316 {
317   guint integer = 0;
318   proto_item *temp_item = NULL;
319   int ret;
320
321   ret = asn1_uint32_value_decode(a, length, &integer);
322   if (ret != ASN1_ERR_NOERROR)
323   {
324     if (tree)
325         {
326       proto_tree_add_text(tree, a->tvb, start, 0,
327        "%s: ERROR: Couldn't parse value: %s",
328         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
329     }
330     return ret;
331   }
332
333   if (i)
334     *i = integer;
335
336   if (tree && hf_id)
337     temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start,
338 a->offset-start, integer);
339
340   if (new_item)
341     *new_item = temp_item;
342
343   return ASN1_ERR_NOERROR;
344 }
345
346 static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
347         proto_item **new_item, guint *i)
348 {
349   guint cls, con, tag;
350   gboolean def;
351   guint length;
352   int start = a->offset;
353   int ret;
354
355   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
356   if (ret != ASN1_ERR_NOERROR)
357   {
358     if (tree)
359         {
360       proto_tree_add_text(tree, a->tvb, start, 0,
361         "%s: ERROR: Couldn't parse header: %s",
362         (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
363         asn1_err_to_str(ret));
364     }
365     return ret;
366   }
367
368   return read_integer_value(a, tree, hf_id, new_item, i, start, length);
369 }
370 /*   display asn.1 Integer type */
371 static void
372 show_integer(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
373 *offset,guint item_len)
374 {
375           proto_tree *acse_tree_itm = NULL;
376           proto_item *itm;
377           int       ret;
378           int           save_len = item_len;
379           int           off      = *offset;
380           itm = proto_tree_add_text(acse_tree, tvb, *offset, item_len,
381                                                                                 "Integer");
382           acse_tree_itm = proto_item_add_subtree(itm, ett_acse_itm);
383           ret = read_integer(asn,acse_tree_itm,0,NULL,&item_len);
384           if (ret == ASN1_ERR_NOERROR )
385                         {
386                                 *offset = asn->offset;
387                                 itm = proto_tree_add_text(acse_tree_itm, tvb, (*offset)-item_len,
388                                                                                         item_len,
389                                                                                         "Integer value: %u",item_len);
390                         }
391           else
392                         {
393                   /* can't dissect item. Skip it. */
394                   *offset = off+ save_len;
395                         }
396
397 }
398 static void
399 show_protocol_version(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
400 *offset,int item_len,int tag)
401 {
402           proto_tree *acse_tree_itm = NULL;
403           proto_item *itm;
404           guint16       flags;
405           gint length;
406 /* do we have enough bytes to dissect this item ? */
407                         if( ( length = tvb_reported_length_remaining(tvb, *offset))  <
408                                                                                 (asn->offset -*offset)+ item_len )
409                         {
410                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
411                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
412                                         return;
413                         }
414
415           itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset -*offset)+
416                                                                 item_len,
417                                                                 val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
418           acse_tree_itm = proto_item_add_subtree(itm, ett_acse_itm);
419           *offset = asn->offset;
420           flags = tvb_get_ntohs(tvb, *offset);
421           proto_tree_add_boolean(acse_tree_itm,hf_protocol_version, tvb, *offset,
422                                                         2, flags);
423           *offset = *offset + item_len;
424           asn->offset = *offset;
425 }
426 static void
427 print_oid_value(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
428 *offset,int item_len)
429 {
430         guint           ret;
431         subid_t         *oid;
432         guint           len;
433         gchar           *display_string;
434         guint           length;
435         guint           start=*offset;
436
437                 ret = asn1_oid_value_decode (asn, item_len, &oid, &len);
438                 if (ret != ASN1_ERR_NOERROR)
439                 {
440                         return ;
441                 }
442                 length = asn->offset - start;
443                 display_string = format_oid(oid, len);
444                 proto_tree_add_text(acse_tree, tvb, *offset,length,"Value:%s",
445                                                         display_string);
446                 g_free(display_string);
447                 (*offset)=start+item_len;
448                 asn->offset = (*offset);
449 }
450 static void
451 print_oid(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int *offset,int
452 item_len,gchar* d_s)
453 {
454         guint           ret;
455         subid_t         *oid;
456         guint           len;
457         guint           nbytes;
458         gchar           *display_string;
459         guint           length;
460         guint           start=*offset;
461
462                 ret = asn1_oid_decode ( asn, &oid, &len, &nbytes);
463
464                 if (ret != ASN1_ERR_NOERROR)
465                 {
466                         return ;
467                 }
468                 length = asn->offset - start;
469                 display_string = format_oid(oid, len);
470                 proto_tree_add_text(acse_tree, tvb, *offset,length,"Value:%s",
471                                                         display_string);
472                 if(d_s)
473                 {
474                         /*   copy OID   */
475                         strcpy(d_s,display_string);
476                 }
477                 g_free(display_string);
478                 (*offset)=start+item_len;
479                 asn->offset = (*offset);
480 }
481
482 static void
483 print_value(proto_tree *acse_tree,tvbuff_t *tvb,int
484 *offset,int item_len)
485 {
486           char    tmp[MAXSTRING];
487                 string_to_hex(tvb_get_ptr(tvb,*offset,item_len),tmp,item_len);
488                 proto_tree_add_text(acse_tree, tvb, *offset, item_len, tmp);
489 }
490 static int
491 get_integer_value(ASN1_SCK *asn,int length,int *offset)
492 {
493         int off = *offset;
494         int asn_off = asn->offset;
495         int item_len = -1;
496         int ret;
497         /* align   pointers */
498         *offset=asn->offset;
499         ret = asn1_uint32_value_decode(asn, length, &item_len);
500         /* return to present position */
501         *offset = off;
502         asn->offset = asn_off;
503
504     if (ret != ASN1_ERR_NOERROR )
505         {
506                 return -1;
507         }
508         else
509         {
510                 return item_len;
511         }
512
513 }
514 static void
515 show_fully_encoded_seq(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
516 *offset,int item_len)
517 {
518           proto_tree *acse_tree_ms = NULL;
519           guint length;
520           guint   type;
521           proto_item *ms;
522           guint   new_item_len;
523           guint   start = *offset;
524           guint   header_len;
525           guint   acse = 0;      /*   no acse   id   */
526           int           old_offset;
527                         /*  print seq */
528                         while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
529                         {
530                                 old_offset = *offset ;
531                         /*  get item type  */
532                         type = tvb_get_guint8(tvb, *offset);
533                         /* skip type */
534                         (*offset)++;
535                         asn->offset = *offset;
536                         /* get length  */
537                                 if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
538                                 {
539                                         (*offset)=start+item_len;
540                                         asn->offset = (*offset);
541                                         return  ;
542                                 }
543                         /* do we have enough bytes to dissect ? */
544                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
545                                                                                                                 new_item_len )
546                         {
547                                         proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
548                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
549                                         (*offset)=start+item_len;
550                                         asn->offset = (*offset);
551                                     return ;
552                         }
553                                 header_len = asn->offset - (*offset) +1;
554                                         ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
555                                                                                 new_item_len+(asn->offset-*offset)+1,
556                                                                                 val_to_str(type, presentation_data_values,
557                                                                                 "Unknown item (0x%02x)"));
558                                 acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
559                                 *offset = asn->offset;
560
561
562                         switch(type)
563                                 {
564                         case PRESENTATION_CONTEXT_IDENTIFIER:
565                                 {
566                                 acse    =       get_integer_value(asn,new_item_len,offset);
567                                 print_value(acse_tree_ms,tvb,offset,new_item_len);
568                                 }
569                                         break;
570                         case ABSTRACT_SYNTAX_NAME:
571                                 print_oid_value(asn,acse_tree_ms,tvb,offset,new_item_len);
572                                         break;
573
574                         case OCTET_ALIGNED:
575                                 break;
576                         case SINGLE_ASN1_TYPE:
577                                 {
578                                                 proto_item *acse_ms;
579                                         /*  yes, we have to call ACSE dissector    */
580                                 acse_ms = proto_tree_add_text(acse_tree_ms, tvb, *offset,
581                                                                                 new_item_len+(asn->offset-*offset),
582                                                                                 "user data");
583                                         /*  call acse dissector  */
584                                 call_app_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,acse_tree_ms);
585                                 }
586                                         break;
587                         case ARBITRARY:
588                                 print_value(acse_tree_ms,tvb,offset,new_item_len);
589                                         break;
590                         default:
591                                         proto_tree_add_text(acse_tree, tvb, *offset,
592                                                                                 new_item_len+(asn->offset-*offset),
593                                         "Unknown asn.1 parameter: (0x%02x)", type);
594                                 }
595                                 *offset = old_offset+new_item_len+header_len;
596                                 item_len-=new_item_len+header_len;
597                         }
598                         /*   align the pointer */
599                         (*offset)=start+item_len;
600                         asn->offset = (*offset);
601
602 }
603
604 static void
605 show_acse_user_information(ASN1_SCK *asn,proto_tree
606 *acse_tree,tvbuff_t *tvb,int *offset,int item_len)
607 {
608           proto_tree *acse_tree_ms = NULL;
609           proto_tree *acse_tree_ab = NULL;
610           guint length;
611           guint   type;
612           proto_item *ms;
613           proto_item *ab;
614           guint   new_item_len;
615           guint   code_item_len;
616           guint   start = *offset;
617           guint   header_len;
618                         /*  get item type  */
619                         type = tvb_get_guint8(tvb, *offset) & 0x1f;
620                         /* skip type */
621                         (*offset)++;
622                         asn->offset = *offset;
623                         /* get length  */
624                                 if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
625                                 {
626                                         (*offset)=start+item_len;
627                                         asn->offset = (*offset);
628                                         return  ;
629                                 }
630
631                         /* do we have enough bytes to dissect ? */
632                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
633                                                                                                                 new_item_len )
634                         {
635                                         proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
636                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
637                                         (*offset)=start+item_len;
638                                         asn->offset = (*offset);
639                                     return ;
640                         }
641                                 header_len = asn->offset - (*offset) +1;
642                                 ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
643                                                                                 new_item_len+(asn->offset-*offset)+1,
644                                                                                 val_to_str(type,response_sequence_top_vals,
645                                                                                 "Unknown item (0x%02x)"));
646                                 acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
647                                 *offset = asn->offset;
648                                 /*  get item type  */
649                                 type = tvb_get_guint8(tvb, *offset) & 0x1f;
650                                 /* do we have user or provider abort ?  */
651                                 ab = proto_tree_add_text(acse_tree_ms, tvb, *offset,
652                                                                                 new_item_len+(asn->offset-*offset),
653                                                                                 val_to_str(type,acse_user_information_vals,
654                                                                                 "Unknown item (0x%02x)"));
655                                 acse_tree_ab = proto_item_add_subtree(ab, ett_acse_ms);
656
657                                 if(type!= ACSE_EXTERNAL)
658                                 {
659                                         (*offset)=start+item_len;
660                                         asn->offset = (*offset);
661                                         return  ;
662                                 }
663
664                                 /*  skip type of item*/
665                                 (*offset)++;
666                                 asn->offset = *offset;
667                                 /* get length  */
668                                 if (read_length(asn, acse_tree_ab, 0, &code_item_len) != 
669 ASN1_ERR_NOERROR)
670                                 {
671                                         (*offset)=start+item_len;
672                                         asn->offset = (*offset);
673                                         return  ;
674                                 }
675                                 /* do we have enough bytes to dissect ? */
676                                 if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
677                                                                                                                 code_item_len )
678                                 {
679                                         proto_tree_add_text(acse_tree_ab, tvb, *offset, code_item_len,
680                                                         "Wrong item.Need %u bytes but have %u", code_item_len,length);
681                                         (*offset)=start+item_len;
682                                         asn->offset = (*offset);
683                                     return ;
684                                 }
685                                 *offset = asn->offset;
686
687                                 show_fully_encoded_seq(asn,acse_tree_ab,tvb,offset,code_item_len);
688                         /*   align the pointer */
689                         (*offset)=start+item_len;
690                         asn->offset = (*offset);
691 }
692
693 static void
694 show_acse_result_source_diagnostic(ASN1_SCK *asn,proto_tree
695 *acse_tree,tvbuff_t *tvb,int *offset,int item_len)
696 {
697           proto_tree *acse_tree_ms = NULL;
698           proto_tree *acse_tree_ab = NULL;
699           guint length;
700           guint   type;
701           proto_item *ms;
702           proto_item *ab;
703           guint   new_item_len;
704           guint   code_item_len;
705           guint   start = *offset;
706           guint   header_len;
707           proto_tree *acse_tree_pr = NULL;
708           proto_item *pr;
709           int   value;
710                         /*  get item type  */
711                         type = tvb_get_guint8(tvb, *offset) & 0x1f;
712                         /* skip type */
713                         (*offset)++;
714                         asn->offset = *offset;
715                         /* get length  */
716                                 if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
717                                 {
718                                         (*offset)=start+item_len;
719                                         asn->offset = (*offset);
720                                         return  ;
721                                 }
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(acse_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(acse_tree, tvb, *offset-1,
735                                                                                 new_item_len+(asn->offset-*offset)+1,
736                                                                                 val_to_str(type,response_sequence_top_vals,
737                                                                                 "Unknown item (0x%02x)"));
738                                 acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
739                                 *offset = asn->offset;
740                         /*  get item type  */
741                         type = tvb_get_guint8(tvb, *offset) & 0x1f;
742                         /* do we have user or provider abort ?  */
743                                 ab = proto_tree_add_text(acse_tree_ms, tvb, *offset,
744                                                                                 new_item_len+(asn->offset-*offset),
745                                                                                 val_to_str(type,acse_associate_source_diagnostic_vals,
746                                                                                 "Unknown item (0x%02x)"));
747                                 acse_tree_ab = proto_item_add_subtree(ab, ett_acse_ms);
748
749                                 /*  skip type of abort*/
750                                 (*offset)++;
751                                 asn->offset = *offset;
752                                 /* get length  */
753                                 if (read_length(asn, acse_tree, 0, &code_item_len) != ASN1_ERR_NOERROR)
754                                 {
755                                         (*offset)=start+item_len;
756                                         asn->offset = (*offset);
757                                         return  ;
758                                 }
759                                 *offset = asn->offset;
760                                 /* do we have enough bytes to dissect ? */
761                                 if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
762                                                                                                                 code_item_len )
763                                 {
764                                         proto_tree_add_text(acse_tree, tvb, *offset, code_item_len,
765                                                         "Wrong item.Need %u bytes but have %u", code_item_len,length);
766                                         (*offset)=start+item_len;
767                                         asn->offset = (*offset);
768                                     return ;
769                                 }
770
771                                 /*  skip type of constant*/
772                                 (*offset)++;
773                                 asn->offset = *offset;
774                                 /* get length  */
775                                 if (read_length(asn, acse_tree_ab, 0, &code_item_len) != 
776 ASN1_ERR_NOERROR)
777                                 {
778                                         (*offset)=start+item_len;
779                                         asn->offset = (*offset);
780                                         return  ;
781                                 }
782                                 /* do we have enough bytes to dissect ? */
783                                 if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
784                                                                                                                 code_item_len )
785                                 {
786                                         proto_tree_add_text(acse_tree_ab, tvb, *offset, code_item_len,
787                                                         "Wrong item.Need %u bytes but have %u", code_item_len,length);
788                                         (*offset)=start+item_len;
789                                         asn->offset = (*offset);
790                                     return ;
791                                 }
792                                 *offset = asn->offset;
793                             value       =       get_integer_value(asn,code_item_len,offset);
794                                 if(type == ACSE_SERVICE_USER )
795                                 {
796                                 pr = proto_tree_add_text(acse_tree_ab, tvb, *offset,
797                                                                 code_item_len+(asn->offset-*offset),
798                                                                 val_to_str(value , acse_service_user_values_vals,
799                                                                 "Unknown item (0x%02x)"));
800                                 }
801                                 else
802                                 {
803                                 pr = proto_tree_add_text(acse_tree_ab, tvb, *offset,
804                                                                 code_item_len+(asn->offset-*offset),
805                                                                 val_to_str(value , acse_service_provider_values_vals,
806                                                                 "Unknown item (0x%02x)"));
807                                 }
808
809                                 acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
810                                 print_value(acse_tree_pr,tvb,offset,code_item_len);
811
812                                 *offset = start+new_item_len+header_len;
813                                 item_len-=new_item_len+header_len;
814                         /*   align the pointer */
815                         (*offset)=start+item_len;
816                         asn->offset = (*offset);
817
818 }
819 static void
820 show_acse_result(ASN1_SCK *asn,proto_tree
821 *acse_tree,tvbuff_t *tvb,int *offset,int item_len)
822 {
823           proto_tree *acse_tree_ms = NULL;
824           guint length;
825           guint   type;
826           proto_item *ms;
827           guint   new_item_len;
828           guint   code_item_len;
829           guint   start = *offset;
830           guint   header_len;
831           proto_tree *acse_tree_pr = NULL;
832           proto_item *pr;
833           int   value;
834                         /*  get item type  */
835                         type = tvb_get_guint8(tvb, *offset) & 0x1f;
836                         /* skip type */
837                         (*offset)++;
838                         asn->offset = *offset;
839                         /* get length  */
840                                 if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
841                                 {
842                                         (*offset)=start+item_len;
843                                         asn->offset = (*offset);
844                                         return  ;
845                                 }
846
847                         /* do we have enough bytes to dissect ? */
848                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
849                                                                                                                 new_item_len )
850                         {
851                                         proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
852                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
853                                         (*offset)=start+item_len;
854                                         asn->offset = (*offset);
855                                     return ;
856                         }
857                                 header_len = asn->offset - (*offset) +1;
858                                 ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
859                                                                                 new_item_len+(asn->offset-*offset)+1,
860                                                                                 val_to_str(type,response_sequence_top_vals,
861                                                                                 "Unknown item (0x%02x)"));
862                                 acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
863                                 *offset = asn->offset;
864                                 /*  skip type */
865                                 (*offset)++;
866                                 asn->offset = *offset;
867                                 /* get length  */
868                                 if (read_length(asn, acse_tree, 0, &code_item_len) != ASN1_ERR_NOERROR)
869                                 {
870                                         (*offset)=start+item_len;
871                                         asn->offset = (*offset);
872                                         return  ;
873                                 }
874                                 /* do we have enough bytes to dissect ? */
875                                 if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
876                                                                                                                 code_item_len )
877                                 {
878                                         proto_tree_add_text(acse_tree, tvb, *offset, code_item_len,
879                                                         "Wrong item.Need %u bytes but have %u", code_item_len,length);
880                                         (*offset)=start+item_len;
881                                         asn->offset = (*offset);
882                                     return ;
883                                 }
884                                 *offset = asn->offset;
885                             value       =       get_integer_value(asn,code_item_len,offset);
886                                 pr = proto_tree_add_text(acse_tree_ms, tvb, *offset,
887                                                                 code_item_len+(asn->offset-*offset),
888                                                                 val_to_str(value , associate_result_values_vals,
889                                                                 "Unknown item (0x%02x)"));
890                                 acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
891                                 print_value(acse_tree_pr,tvb,offset,code_item_len);
892
893                                 *offset = start+new_item_len+header_len;
894                                 item_len-=new_item_len+header_len;
895                         /*   align the pointer */
896                         (*offset)=start+item_len;
897                         asn->offset = (*offset);
898 }
899
900 static void
901 show_oid(ASN1_SCK *asn,proto_tree
902 *acse_tree,tvbuff_t *tvb,int *offset,int item_len,const value_string* 
903 v_s,gchar* oid)
904 {
905           proto_tree *acse_tree_ms = NULL;
906           guint length;
907           guint   type;
908           proto_item *ms;
909           guint   new_item_len;
910           guint   start = *offset;
911           guint   header_len;
912           int           old_offset;
913                                 old_offset = *offset ;
914                         /*  get item type  */
915                         type = tvb_get_guint8(tvb, *offset) & 0x1f;
916                         /* skip type */
917                         (*offset)++;
918                         asn->offset = *offset;
919                         /* get length  */
920                                 if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
921                                 {
922                                         (*offset)=start+item_len;
923                                         asn->offset = (*offset);
924                                         return  ;
925                                 }
926
927                         /* do we have enough bytes to dissect ? */
928                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
929                                                                                                                 new_item_len )
930                         {
931                                         proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
932                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
933                                         (*offset)=start+item_len;
934                                         asn->offset = (*offset);
935                                     return ;
936                         }
937                                 header_len = asn->offset - (*offset) +1;
938                                 ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
939                                                                                 new_item_len+(asn->offset-*offset)+1,
940                                                                                 val_to_str(type, v_s,
941                                                                                 "Unknown item (0x%02x)"));
942                                 acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
943                                 *offset = asn->offset;
944                                 print_oid(asn,acse_tree_ms,tvb,offset,new_item_len,oid);
945                                 *offset = old_offset+new_item_len+header_len;
946                                 item_len-=new_item_len+header_len;
947                         /*   align the pointer */
948                         (*offset)=start+item_len;
949                         asn->offset = (*offset);
950 }
951 static void
952 show_fully_encoded_data(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
953 *tvb,int *offset,int item_len)
954 {
955           proto_tree *acse_tree_ms = NULL;
956           proto_tree *acse_tree_pc = NULL;
957           guint    length;
958           guint   type;
959           guint   header_len;
960           proto_item *ms;
961           guint   new_item_len;
962           guint   start = asn->offset;
963           guint   item_length = item_len;
964           acse_tree_pc = acse_tree;
965
966 /* do we have enough bytes to dissect ? */
967                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < (guint)item_len )
968                         {
969                                         proto_tree_add_text(acse_tree_pc, tvb, *offset, item_len,
970                                                         "Wrong item.Need %u bytes but have %u", item_len,length);
971                                         /*   align the pointer */
972                                         (*offset)=start+item_length;
973                                         asn->offset = (*offset);
974                                         return ;
975                         }
976                         *offset =asn->offset;
977                         start = *offset;
978                         /*  read the rest */
979                         while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
980                         {
981                                 int old_offset = *offset;
982                         /*  get item type  */
983                         type = tvb_get_guint8(tvb, *offset);
984                         /* skip type */
985                         (*offset)++;
986                         asn->offset = *offset;
987                         /* get length  */
988                                 if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
989                                                                 ASN1_ERR_NOERROR)
990                                 {
991                                         /*   align the pointer */
992                                         (*offset)=start+item_length;
993                                         asn->offset = (*offset);
994                                         return  ;
995                                 }
996                                 header_len = asn->offset - (*offset) +1;
997                         /* do we have enough bytes to dissect ? */
998                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  <
999                                                                                                                 new_item_len )
1000                         {
1001                                         proto_tree_add_text(acse_tree_pc, tvb, *offset, new_item_len,
1002                                                         "Wrong item.Need %u bytes but have %u", new_item_len,length);
1003                                         /*   align the pointer */
1004                                         (*offset)=start+item_length;
1005                                         asn->offset = (*offset);
1006                                         return ;
1007                         }
1008                                 ms = proto_tree_add_text(acse_tree_pc, tvb, *offset-1,
1009                                                                                 new_item_len+(asn->offset-*offset)+1,
1010                                                                                 val_to_str(type, presentation_context_definition_vals,
1011                                                                                 "Unknown item (0x%02x)"));
1012                                 acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
1013                                 *offset = asn->offset;
1014
1015
1016                         switch(type)
1017                                 {
1018
1019                         case SEQUENCE:
1020                         show_fully_encoded_seq(asn,acse_tree_ms,tvb,offset,new_item_len);
1021                         *offset = old_offset+(new_item_len+header_len);
1022                                         break;
1023
1024                         default:
1025                                         proto_tree_add_text(acse_tree_ms, tvb, *offset,
1026                                                                                 new_item_len+(asn->offset-*offset),
1027                                         "Unknown asn.1 parameter: (0x%02x)", type);
1028                                         *offset = old_offset+(new_item_len+header_len);
1029                                 }
1030                                 item_len = item_len -  (new_item_len+header_len);
1031
1032                         }
1033
1034
1035                                         /*   align the pointer */
1036                                         (*offset)=start+item_length;
1037                                         asn->offset = (*offset);
1038 }
1039 static void
1040 show_abort_reason(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
1041 *tvb,int *offset,int item_len)
1042 {
1043         gint            length;
1044         gint            value;
1045     proto_tree  *acse_tree_pc = NULL;
1046         proto_item      *itu;
1047         guint           new_item_len;
1048         guint           start = *offset;
1049         int                     save_len = item_len;
1050 /* do we have enough bytes to dissect this item ? */
1051                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
1052                         {
1053                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
1054                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
1055                                                         *offset = asn->offset;
1056                                                         return;
1057                         }
1058
1059                         if(item_len <= 0)
1060                         {
1061                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
1062                                                         "Reason not specified");
1063                                                         *offset = asn->offset;
1064                                                         return;
1065                         }
1066                         itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
1067                                         "Reason");
1068                         acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
1069                         (*offset)++; /* skip type  */
1070                         asn->offset =  *offset;
1071                         item_len--;
1072                         /* get length  */
1073                                 if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
1074                                                                 ASN1_ERR_NOERROR)
1075                                 {
1076                                                         *offset = asn->offset;
1077                                                         return;
1078                                 }
1079                         /*  try to get reason  */
1080                         value   =       get_integer_value(asn,new_item_len,offset);
1081
1082                         proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
1083                                         val_to_str(value,abort_reason,"Unknown item (0x%02x)"));
1084                         item_len-=(asn->offset-*offset)+new_item_len;
1085                         *offset = asn->offset+new_item_len;
1086                         asn->offset = *offset;
1087                         /*  do we have User information field  ?  */
1088                         if(item_len > 0)
1089                         {
1090                                 show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
1091                         }
1092                         /*   align the pointer */
1093                         (*offset)=start+save_len;
1094                         asn->offset = (*offset);
1095 }
1096
1097 static void
1098 show_disconnect_pdu(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
1099 *tvb,int *offset,int item_len)
1100 {
1101         gint            length;
1102         gint            value;
1103     proto_tree  *acse_tree_pc = NULL;
1104         proto_item      *itu;
1105         guint           new_item_len;
1106         guint           start = *offset;
1107         int                     save_len = item_len;
1108 /* do we have enough bytes to dissect this item ? */
1109                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
1110                         {
1111                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
1112                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
1113                                                         *offset = asn->offset;
1114                                                         return;
1115                         }
1116
1117                         if(item_len <= 0)
1118                         {
1119                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
1120                                                         "Reason not specified");
1121                                                         *offset = asn->offset;
1122                                                         return;
1123                         }
1124                         itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
1125                                         "Reason");
1126                         acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
1127                         (*offset)++; /* skip type  */
1128                         asn->offset =  *offset;
1129                         item_len--;
1130                         /* get length  */
1131                                 if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
1132                                                                 ASN1_ERR_NOERROR)
1133                                 {
1134                                                         *offset = asn->offset;
1135                                                         return;
1136                                 }
1137                         /*  try to get reason  */
1138                         value   =       get_integer_value(asn,new_item_len,offset);
1139
1140                         proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
1141                                         val_to_str(value,release_response_reason,"Unknown item (0x%02x)"));
1142                         item_len-=(asn->offset-*offset)+new_item_len;
1143                         *offset = asn->offset+new_item_len;
1144                         asn->offset = *offset;
1145                         /*  do we have User information field  ?  */
1146                         if(item_len > 0)
1147                         {
1148                                 show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
1149                         }
1150                         /*   align the pointer */
1151                         (*offset)=start+save_len;
1152                         asn->offset = (*offset);
1153 }
1154
1155 static void
1156 show_finish_pdu(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
1157 *tvb,int *offset,int item_len)
1158 {
1159         gint            length;
1160         gint            value;
1161     proto_tree  *acse_tree_pc = NULL;
1162         proto_item      *itu;
1163         guint           new_item_len;
1164         guint           start = *offset;
1165         int                     save_len = item_len;
1166 /* do we have enough bytes to dissect this item ? */
1167                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
1168                         {
1169                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
1170                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
1171                                                         *offset = asn->offset;
1172                                                         return;
1173                         }
1174
1175                         if(item_len <= 0)
1176                         {
1177                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
1178                                                         "Reason not specified");
1179                                                         *offset = asn->offset;
1180                                                         return;
1181                         }
1182                         itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
1183                                         "Reason");
1184                         acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
1185                         (*offset)++; /* skip type  */
1186                         asn->offset =  *offset;
1187                         item_len--;
1188                         /* get length  */
1189                                 if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
1190                                                                 ASN1_ERR_NOERROR)
1191                                 {
1192                                                         *offset = asn->offset;
1193                                                         return;
1194                                 }
1195                         /*  try to get reason  */
1196                         value   =       get_integer_value(asn,new_item_len,offset);
1197
1198                         proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
1199                                         val_to_str(value,release_request_reason,"Unknown item (0x%02x)"));
1200                         item_len-=(asn->offset-*offset)+new_item_len;
1201                         *offset = asn->offset+new_item_len;
1202                         asn->offset = *offset;
1203                         /*  do we have User information field  ?  */
1204                         if(item_len > 0)
1205                         {
1206                                 show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
1207                         }
1208                         /*   align the pointer */
1209                         (*offset)=start+save_len;
1210                         asn->offset = (*offset);
1211 }
1212 static void
1213 show_user_data(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
1214 *offset,int item_len,int tag)
1215 {
1216           proto_tree *acse_tree_ud = NULL;
1217           proto_tree *acse_tree_pc = NULL;
1218           proto_item *itm;
1219           proto_item *itu;
1220           guint   start = asn->offset;
1221           guint   item_length = item_len;
1222
1223                         itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset -*offset)+
1224                                                                         item_len,       "User data");
1225                         acse_tree_ud = proto_item_add_subtree(itm, ett_acse_ms);
1226                         itu = proto_tree_add_text(acse_tree_ud, tvb,
1227                                                                                 *offset,item_len+(asn->offset-*offset),
1228                                         val_to_str(tag, user_data_values_vals,"Unknown item (0x%02x)"));
1229                         acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
1230                         switch(tag)
1231                         {
1232                         case SIMPLY_ENCODED_DATA:
1233                                 break;
1234                         case FULLY_ENCODED_DATA:
1235                                 show_fully_encoded_data(asn,acse_tree_pc,tvb,offset,item_len);
1236                                 break;
1237                         default:
1238                                 break;
1239                         }
1240
1241
1242                         /*   align the pointer */
1243                         (*offset)=start+item_length;
1244                         asn->offset = (*offset);
1245
1246 }
1247
1248 /* if we can't dissect */
1249 static void
1250 dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
1251                     proto_tree *tree, const char *field_name, int ret)
1252 {
1253         char *errstr;
1254         errstr = asn1_err_to_str(ret);
1255
1256         if (tree != NULL)
1257         {
1258                 proto_tree_add_text(tree, tvb, offset, 0,
1259                     "ERROR: Couldn't parse %s: %s", field_name, errstr);
1260                 call_dissector(data_handle,
1261                     tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
1262         }
1263 }
1264
1265 /* display request top sequence  */
1266 static void
1267 show_request_sequence_top(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
1268 *tvb,packet_info *pinfo,int *offset,int item_len)
1269 {
1270         int ret;
1271         guint cls, con, tag,len1;
1272         gint  type;
1273         gboolean def;
1274         proto_item *itm;
1275         gint length;
1276
1277         while(item_len > 0 )
1278         {
1279                         int offset_save = *offset;
1280 /* do we have enough bytes to dissect this item ? */
1281                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
1282                         {
1283                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
1284                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
1285                                         break;
1286                         }
1287                 /*   get  tag     */
1288                         type = tvb_get_guint8(tvb, *offset);
1289                 /* decode header  */
1290                         ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
1291
1292                         if (ret != ASN1_ERR_NOERROR)
1293                         {
1294                                                         dissect_parse_error(tvb, *offset, pinfo, acse_tree,
1295                                                                         "sequence error", ret);
1296                                 break;
1297                         }
1298                         /* add header  */
1299                         item_len = item_len - (asn->offset - *offset);
1300                         offset_save += (asn->offset - *offset);
1301                                                 /*
1302                                                 * [APPLICATION <tag>]
1303                                                 */
1304                                                 switch (tag)
1305                                                         {
1306                                                                 case USER_INFORMATION:
1307                                                                         show_acse_user_information(asn,acse_tree,tvb,offset,len1);
1308                                                                         break;
1309                                                                 case CALLED_AE_QUALIFIER:
1310                                                                 case CALLING_AE_QUALIFIER:
1311                                                                         {
1312                                                                         proto_tree *acse_tree_pr = NULL;
1313                                                                         proto_item *pr;
1314                                                                         pr = proto_tree_add_text(acse_tree,tvb,*offset,
1315                                                                         len1+(asn->offset-*offset),
1316                                                                         val_to_str(tag ,request_sequence_top_vals,
1317                                                                         "Unknown item (0x%02x)"));
1318                                                                         acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
1319                                                                         show_integer(asn,acse_tree_pr,tvb,offset,len1);
1320                                                                         }
1321                                                                         break;
1322                                                                 case APPLICATION_CONTEXT_NAME:
1323                                                                 case CALLED_AP_TITLE:
1324                                                                 case CALLING_AP_TITLE:
1325                                                                 case CALLED_AP_INVOKATION_ID:
1326                                                                 case CALLED_AE_INVOKATION_ID:
1327                                                                 case CALLING_AP_INVOKATION_ID:
1328                                                                 case CALLING_AE_INVOKATION_ID:
1329                                                                 {
1330                                                                         gchar oid_string[MAXSTRING];
1331                                                                         show_oid(asn,acse_tree,tvb,offset,len1,(const 
1332 value_string*)&request_sequence_top_vals,
1333                                                                                                 (gchar*)&oid_string);
1334                                                                         if(tag == APPLICATION_CONTEXT_NAME )
1335                                                                         {
1336                                                                                 guint   pos_in_string;
1337                                                                                 /* try to find real OID string from given  */
1338                                                                                 /* function could return "1.0.8571.1.1" or "1.0.8571.1.1 iso.0.8571.1.1" */
1339                                                                                 /* so try to find first blank and strip string */
1340                                                                                 for(pos_in_string=0;pos_in_string<strlen(oid_string);pos_in_string++)
1341                                                                                 {
1342                                                                                         if( oid_string[pos_in_string] == ' ' )
1343                                                                                         {
1344                                                                                                 oid_string[pos_in_string] = 0x00;
1345                                                                                                 break;
1346                                                                                         }
1347                                                                                 }
1348                                                                                 /* try to get subdissector handler using given OID */
1349                                                                                 if(pos_in_string )
1350                                                                                 {
1351                                                                                         if( !(app_handle = dissector_get_string_handle(application_dissector_table, oid_string)  ))
1352                                                                                         {
1353                                                                                                 proto_tree_add_text(acse_tree,tvb,*offset,len1,"Unknown OID");
1354                                                                                         }
1355                                                                                 }
1356                                                                         }
1357                                                                 }
1358                                                                         break;
1359                                                                 case PROTOCOL_VERSION:
1360                                                                         show_protocol_version(asn,acse_tree,tvb,offset,len1,tag);
1361                                                                         break;
1362                                                                 default:
1363                                                                         itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset
1364                                                                                                                                 -*offset)+ len1,
1365                                                                                         "Unknown tag: %x",tag);
1366                                                         }
1367                 item_len-=len1;
1368                 *offset = asn->offset = offset_save+len1;;
1369         }
1370 }
1371 /* display response top sequence  */
1372 static void
1373 show_response_sequence_top(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
1374 *tvb,packet_info *pinfo,int *offset,int item_len)
1375 {
1376         int ret;
1377         guint cls, con, tag,len1;
1378         gint  type;
1379         gboolean def;
1380         proto_item *itm;
1381         gint length;
1382
1383         while(item_len > 0 )
1384         {
1385                         int offset_save = *offset;
1386 /* do we have enough bytes to dissect this item ? */
1387                         if( ( length =tvb_reported_length_remaining(tvb, *offset))  < item_len )
1388                         {
1389                                         proto_tree_add_text(acse_tree, tvb, *offset, item_len,
1390                                                         "Wrong Item.Need %u bytes but have %u", item_len,length);
1391                                         break;
1392                         }
1393                 /*   get  tag     */
1394                         type = tvb_get_guint8(tvb, *offset);
1395                 /* decode header  */
1396                         ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
1397
1398                         if (ret != ASN1_ERR_NOERROR)
1399                         {
1400                                                         dissect_parse_error(tvb, *offset, pinfo, acse_tree,
1401                                                                         "sequence error", ret);
1402                                 break;
1403                         }
1404                         /* add header  */
1405                         item_len = item_len - (asn->offset - *offset);
1406                         offset_save += (asn->offset - *offset);
1407                                                 /*
1408                                                 * [APPLICATION <tag>]
1409                                                 */
1410                                                 switch (tag)
1411                                                         {
1412                                                                 case ACSE_RESULT:
1413                                                                         show_acse_result(asn,acse_tree,tvb,offset,len1);
1414                                                                         break;
1415                                                                 case ACSE_RESULT_SOURCE_DIAGNOSTIC:
1416                                                                         show_acse_result_source_diagnostic(asn,acse_tree,tvb,offset,len1);
1417                                                                         break;
1418                                                                 case USER_INFORMATION:
1419                                                                         show_acse_user_information(asn,acse_tree,tvb,offset,len1);
1420                                                                         break;
1421
1422                                                                 case RESPONDING_AE_QUALIFIER:
1423                                                                         {
1424                                                                         proto_tree *acse_tree_pr = NULL;
1425                                                                         proto_item *pr;
1426                                                                         pr = proto_tree_add_text(acse_tree,tvb,*offset,
1427                                                                         len1+(asn->offset-*offset),
1428                                                                         val_to_str(tag ,response_sequence_top_vals,
1429                                                                         "Unknown item (0x%02x)"));
1430                                                                         acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
1431                                                                         show_integer(asn,acse_tree_pr,tvb,offset,len1);
1432                                                                         }
1433                                                                         break;
1434                                                                 case APPLICATION_CONTEXT_NAME:
1435                                                                 case RESPONDING_AP_TITLE:
1436                                                                 case RESPONDING_AP_INVOKATION_ID:
1437                                                                 case RESPONDING_AE_INVOKATION_ID:
1438                                                                         show_oid(asn,acse_tree,tvb,offset,len1,(const 
1439 value_string*)&response_sequence_top_vals,NULL);
1440                                                                         break;
1441                                                                 case PROTOCOL_VERSION:
1442                                                                         show_protocol_version(asn,acse_tree,tvb,offset,len1,tag);
1443                                                                         break;
1444                                                                 default:
1445                                                                         itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset
1446                                                                                                                                 -*offset)+ len1,
1447                                                                                         "Unknown tag: %x",tag);
1448                                                         }
1449                 item_len-=len1;
1450                 *offset = asn->offset = offset_save+len1;
1451         }
1452 }
1453
1454 /*
1455 * Dissect a pdu.
1456 */
1457 static int
1458 dissect_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
1459                         *tree)
1460 {
1461   proto_item *ti;
1462   proto_tree *acse_tree = NULL;
1463   guint length;
1464   guint       rest_len;
1465   guint  s_type;
1466   ASN1_SCK asn;
1467   guint cp_type_len;
1468 /* get type of tag      */
1469         s_type = tvb_get_guint8(tvb, offset);
1470                 /*  set up type of pdu */
1471         if (check_col(pinfo->cinfo, COL_INFO))
1472                                         col_add_str(pinfo->cinfo, COL_INFO,
1473                                                 val_to_str(session->spdu_type, ses_vals, "Unknown pdu type (0x%02x)"));
1474   if (tree)
1475         {
1476                 ti = proto_tree_add_item(tree, proto_acse, tvb, offset, -1,
1477                     FALSE);
1478                 acse_tree = proto_item_add_subtree(ti, ett_acse);
1479         }
1480         offset++;
1481 /*    open asn.1 stream    */
1482         asn1_open(&asn, tvb, offset);
1483
1484         switch(session->spdu_type)
1485         {
1486                 case SES_REFUSE:
1487                 case SES_CONNECTION_REQUEST:
1488                 case SES_CONNECTION_ACCEPT:
1489                         proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
1490
1491                         if (read_length(&asn, acse_tree, hf_cp_type_message_length, &cp_type_len)
1492                                                         != ASN1_ERR_NOERROR)
1493                                         {
1494                                         return  FALSE;
1495                                         }
1496                         /* skip length   */
1497                         offset = asn.offset;
1498                         /* do we have enough bytes to dissect ? */
1499                         if( ( length =tvb_reported_length_remaining(tvb, offset))  < cp_type_len
1500                                         )
1501                         {
1502                                 if(tree)
1503                                 {
1504                                         proto_tree_add_text(acse_tree, tvb, offset, -1,
1505                                                         "Wrong pdu.Need %u bytes but have %u", cp_type_len,length);
1506                                 }
1507                         return FALSE;
1508                         }
1509                         if(tree)
1510                         {
1511                                 if(session->spdu_type == SES_CONNECTION_REQUEST)
1512                                 {
1513                                 show_request_sequence_top(&asn,acse_tree,tvb,pinfo,&offset,cp_type_len);
1514                                 }
1515                                 else
1516                                 {
1517                                 show_response_sequence_top(&asn,acse_tree,tvb,pinfo,&offset,cp_type_len);
1518                                 }
1519
1520                         }
1521                                 break;
1522                 case SES_FINISH:
1523                         proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
1524                                 /* get length  */
1525                                 if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1526                                                 {
1527                                         return  FALSE;
1528                                                 }
1529                                 /* skip length   */
1530                                 offset = asn.offset;
1531                                 /* do we have enough bytes to dissect ? */
1532                                 if( ( length =tvb_reported_length_remaining(tvb, offset))  < rest_len )
1533                                 {
1534                                         if(tree)
1535                                         {
1536                                         proto_tree_add_text(acse_tree, tvb, offset, -1,
1537                                                         "Wrong pdu.Need %u bytes but have %u", rest_len,length);
1538                                         }
1539                                 return FALSE;
1540                                 }
1541                                 show_finish_pdu(&asn,acse_tree,tvb,&offset,rest_len);
1542                                 break;
1543                 case SES_DISCONNECT:
1544                         proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
1545                                 /* get length  */
1546                                 if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1547                                                 {
1548                                         return  FALSE;
1549                                                 }
1550                                 /* skip length   */
1551                                 offset = asn.offset;
1552                                 /* do we have enough bytes to dissect ? */
1553                                 if( ( length =tvb_reported_length_remaining(tvb, offset))  < rest_len )
1554                                 {
1555                                         if(tree)
1556                                         {
1557                                         proto_tree_add_text(acse_tree, tvb, offset, -1,
1558                                                         "Wrong pdu.Need %u bytes but have %u", rest_len,length);
1559                                         }
1560                                 return FALSE;
1561                                 }
1562                                 show_disconnect_pdu(&asn,acse_tree,tvb,&offset,rest_len);
1563                                 break;
1564                 case SES_ABORT:
1565                         proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
1566                                 /* get length  */
1567                                 if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1568                                                 {
1569                                         return  FALSE;
1570                                                 }
1571                                 /* skip length   */
1572                                 offset = asn.offset;
1573                                 /* do we have enough bytes to dissect ? */
1574                                 if( ( length =tvb_reported_length_remaining(tvb, offset))  < rest_len )
1575                                 {
1576                                         if(tree)
1577                                         {
1578                                         proto_tree_add_text(acse_tree, tvb, offset, -1,
1579                                                         "Wrong pdu.Need %u bytes but have %u", rest_len,length);
1580                                         }
1581                                 return FALSE;
1582                                 }
1583                                 show_abort_reason(&asn,acse_tree,tvb,&offset,rest_len);
1584                                 break;
1585                 default:
1586                         {
1587                                 proto_item *ms;
1588                                 proto_tree *acse_tree_ms = NULL;
1589                                 /* back to length  */
1590                                   offset--;
1591                                 /* get length  */
1592                                 if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1593                                                 {
1594                                         return  FALSE;
1595                                                 }
1596                                 ms = proto_tree_add_text(acse_tree, tvb, offset, rest_len,
1597                                                                                 val_to_str(session->spdu_type, ses_vals, "Unknown pdu type (0x%02x)"));
1598                                 acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
1599                                 show_user_data(&asn,acse_tree_ms,tvb,&offset,rest_len,s_type);
1600                         }
1601         }
1602 /*    close asn.1 stream    */
1603           asn1_close(&asn, &offset);
1604
1605         return offset;
1606 }
1607
1608 /*
1609 * Dissect ACSE PDUs inside a PPDU.
1610 */
1611 static void
1612 dissect_acse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1613 {
1614         int offset = 0;
1615 /* first, try to check length   */
1616 /* do we have at least 2 bytes  */
1617         if (!tvb_bytes_exist(tvb, 0, 2))
1618         {
1619         proto_tree_add_text(tree, tvb, offset, 
1620 tvb_reported_length_remaining(tvb,offset),
1621                                                                 "User data");
1622                         return;  /* no, it isn't a ACSE PDU */
1623         }
1624 /* do we have spdu type from the session dissector?  */
1625         if( !pinfo->private_data )
1626                                 {
1627                                 if(tree)
1628                                                 {
1629                                         proto_tree_add_text(tree, tvb, offset, -1,
1630                                                         "Internal error:can't get spdu type from session dissector.");
1631                                         return  ;
1632                                                 } 
1633                                 }
1634         else
1635                                 {
1636                                         session  = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
1637                                         if(session->spdu_type == 0 )
1638                                         {
1639                                                 if(tree)
1640                                                 {
1641                                         proto_tree_add_text(tree, tvb, offset, -1,
1642                                                         "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
1643                                         return  ;
1644                                                 }
1645                                         }
1646                                 }
1647 /*  ACSE has only AARQ,AARE,RLRQ,RLRE,ABRT type of pdu */
1648 /*  reject everything else                              */
1649 /*  data pdu is not ACSE pdu and has to go directly to app dissector */
1650                         switch(session->spdu_type)
1651                         {
1652                 case SES_REFUSE:                                        /*   RLRE   */
1653                 case SES_CONNECTION_REQUEST:            /*   AARQ   */
1654                 case SES_CONNECTION_ACCEPT:                     /*   AARE   */
1655                 case SES_DISCONNECT:                            /*   RLRQ   */
1656                 case SES_FINISH:                                        /*   RLRE   */
1657                 case SES_ABORT:                                         /*   ABRT   */
1658                         break;
1659                 case SES_DATA_TRANSFER:
1660                         call_app_dissector(tvb,offset,tvb_reported_length_remaining(tvb, offset) 
1661 ,pinfo,tree,tree);
1662                         return;
1663                 default:
1664                         return;
1665                         }
1666
1667         /*  we can't make any additional checking here   */
1668         /*  postpone it before dissector will have more information */
1669
1670         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1671                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACSE");
1672         if (check_col(pinfo->cinfo, COL_INFO))
1673                 col_clear(pinfo->cinfo, COL_INFO);
1674         /* save pointers for calling the app dissector  */
1675         global_tree = tree;
1676         global_pinfo = pinfo;
1677
1678         while (tvb_reported_length_remaining(tvb, offset) > 0)
1679                         {
1680                 offset = dissect_pdu(tvb, offset, pinfo, tree);
1681                 if(offset == FALSE )
1682                                                         {
1683                                                                         proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
1684                                                                         offset = tvb_length(tvb);
1685                                                                         break;
1686                                                         }
1687                         }
1688 }
1689
1690 void
1691 proto_register_acse(void)
1692 {
1693         static hf_register_info hf[] =
1694         {
1695                 {
1696                         &hf_acse_type,
1697                         {
1698                                 "PDU Type",
1699                                 "acse.type",
1700                                 FT_UINT8,
1701                                 BASE_DEC,
1702                                 VALS(acse_vals),
1703                                 0x0,
1704                                 "", HFILL
1705                         }
1706                 },
1707                 {
1708                         &hf_cp_type_message_length,
1709                         {
1710                                 "Message Length",
1711                                 "cp_type.message_length",
1712                                 FT_UINT32,
1713                                 BASE_DEC,
1714                                 NULL,
1715                                 0x0,
1716                                 "CP type Message Length",
1717                                 HFILL
1718                         }
1719                 },
1720                 {
1721                         &hf_protocol_version,
1722                         {
1723                                 "Protocol version 1",
1724                                 "acse.protocol.version",
1725                                 FT_BOOLEAN, 16,
1726                                 NULL,
1727                                 ACSE_PROTOCOL_VERGION,
1728                                 "Protocol version 1",
1729                                 HFILL
1730                         }
1731                 },
1732         };
1733
1734         static gint *ett[] =
1735         {
1736                 &ett_acse,
1737                 &ett_acse_param,
1738                 &ett_acse_rc,
1739                 &ett_acse_ms,
1740                 &ett_acse_itm,
1741         };
1742         module_t *acse_module;
1743
1744
1745         proto_acse = proto_register_protocol(PROTO_STRING_ACSE, "ACSE", "acse");
1746         proto_register_field_array(proto_acse, hf, array_length(hf));
1747         proto_register_subtree_array(ett, array_length(ett));
1748
1749         acse_module = prefs_register_protocol(proto_acse, NULL);
1750
1751         /*
1752          * Register the dissector by name, so other dissectors can
1753          * grab it by name rather than just referring to it directly
1754          */
1755         register_dissector("acse", dissect_acse, proto_acse);
1756         application_dissector_table = register_dissector_table("acse.application_context", "Application context OID", FT_STRING, BASE_NONE); 
1757 }
1758
1759 void
1760 proto_reg_handoff_acse(void)
1761 {
1762         /*   find data dissector  */
1763         data_handle = find_dissector("data");
1764
1765 }
1766
1767