3 * Routine to dissect ISO 8823 OSI Presentation Protocol packets
7 * Yuriy Sidelnikov <YSidelnikov@hotmail.com>
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@ethereal.com>
11 * Copyright 1998 Gerald Combs
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.
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.
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.
33 #include <epan/packet.h>
38 #include "packet-pres.h"
39 #include "packet-frame.h"
40 #include <epan/prefs.h>
42 #include <epan/strutil.h>
44 #include <epan/asn1.h>
45 #include "format-oid.h"
47 #include "packet-ses.h"
48 extern const value_string ses_vals[];
50 /* pres header fields */
51 static int proto_pres = -1;
52 /* type of session envelop */
53 static struct SESSION_DATA_STRUCTURE* session = NULL;
54 static int hf_pres_rc_type = -1;
55 static int hf_pres_ms_type = -1;
56 static int hf_pres_seq_type = -1;
57 static int hf_pres_protocol_version =-1;
58 /* pres fields defining a sub tree */
59 static gint ett_pres = -1;
60 static gint ett_pres_param = -1;
61 static gint ett_pres_rc = -1;
62 static gint ett_pres_ms = -1;
63 static gint ett_pres_itm = -1;
66 ----------------------------------------------------------------------------------------------------------*/
67 static dissector_handle_t acse_handle = NULL;
69 static int hf_pres_type = -1;
70 static int hf_pres_length = -1;
71 static int hf_value = -1;
74 static int hf_cp_type_message_length = -1;
76 static int hf_protocol_version = -1;
77 static int hf_context_management = -1;
78 static int hf_restoration = -1;
81 static const value_string pres_vals[] =
83 {PRES_CONNECTION_REQUEST_CONFIRM, "Connection request/confirm PDU" },
84 {PRES_CONNECTION_REFUSE, "Connection refuse PDU" },
88 static const value_string cr_vals[] =
90 {MODE_SELECTOR, "Mode Selector"},
91 {SEQUENCE_TOP, "Sequence"},
96 static const value_string sequence_top_vals[] =
98 {CALLED_PRESENTATION_SELECTOR, "Called presentation selector"},
99 {CALLING_PRESENTATION_SELECTOR, "Calling presentation selector"},
100 {PRESENTATION_CONTEXT_DEFINITION_LIST, "Presentation context definition list"},
101 {RESPONDING_PRESENTATION_SELECTOR, "Responding presentation selector"},
102 {PROTOCOL_VERSION, "Protocol version"},
103 {PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST, "Presentation context definition result list"},
104 {PRESENTATION_REQUIREMENTS,"Presentation requirements"},
105 {DEFAULT_CONTEXT_NAME,"Default context name"},
106 {USER_SESSION_REQUIREMENTS,"User session requirements"},
107 {DEFAULT_CONTEXT_RESULT,"Default context result"},
108 {PROVIDER_REASON,"Provider reason"},
111 static const value_string sequence_list_vals[] =
113 {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
114 {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
115 {TRANSFER_SYNTAX_NAMES,"Transfer syntax names"},
118 static const value_string sequence_list_result_vals[] =
120 {PRESENTATION_RESULT,"Result"},
121 {PRESENTATION_RESULT_INTEGER,"Integer"},
122 {PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME,"Transfer syntax name"},
125 static const value_string presentation_context_definition_vals[] =
127 {SEQUENCE, "Sequence"},
130 static const value_string sequence_list_result_values_vals[] =
132 {PRESENTATION_RESULT_ACCEPTANCE,"Acceptance"},
133 {PRESENTATION_RESULT_USER_REJECTION,"User rejection"},
134 {PRESENTATION_RESULT_PROVIDER_REJECTION,"Provider rejection"},
137 static const value_string provider_reason_values_vals[] =
139 {REASON_NOT_SPECIFIED,"Reason not specified"},
140 {TEMPORARY_CONGESTION,"Temporary congestion"},
141 {LOCAL_LIMIT_EXCEEDED,"Local limit exceeded"},
142 {CALLED_PRESENTATION_ADDRESS_UNKNOWN,"Called presentation address unknown"},
143 {PROTOCOL_VERSION_NOT_SUPPORTED,"Protocol version not supported"},
144 {DEFAULT_CONTEXT_NOT_SUPPORTED,"Default context not supported"},
145 {USER_DATA_NOT_READABLE,"User data not readable"},
146 {NO_PSAP_AVAILABLE,"No PSAP available"},
150 static const value_string user_data_values_vals[] =
152 {SIMPLY_ENCODED_DATA,"Simply encoded data"},
153 {FULLY_ENCODED_DATA,"Fully encoded data "},
156 static const value_string presentation_data_values[] =
158 {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
159 {SINGLE_ASN1_TYPE,"Single ASN.1 type"},
160 {OCTET_ALIGNED,"Octet aligned"},
161 {ARBITRARY,"Arbitrary"},
162 {DATA_BLOCK,"Data block"},
165 static const value_string provider_abort_values_vals[] =
167 {PR_REASON_NOT_SPECIFIED,"Reason not specified"},
168 {UNRECOGNIZED_PDU,"Unrecognized ppdu"},
169 {UNEXPECTED_PDU,"Unexpected ppdu"},
170 {UNEXPECTED_SESSION_SERVICE_PRIMITIVE,"Unexpected session service primitive"},
171 {UNRECOGNIZED_PPDU_PARAMETER,"Unrecognized ppdu parameter"},
172 {UNEXPECTED_PPDU_PARAMETER,"Unexpected ppdu parameter"},
173 {INVALID_PPDU_PARAMETER_VALUE,"Invalid ppdu parameter value"},
176 static const value_string event_identifier_values_vals[] =
178 {REASON_CP_PPDU,"cp PPDU"},
179 {REASON_CPA_PPDU,"cpa PPDU"},
180 {REASON_CPR_PPDU,"cpr PPDU"},
181 {REASON_ARU_PPDU,"aru PPDU"},
182 {REASON_ARP_PPDU,"arp PPDU"},
183 {REASON_AC_PPDU,"ac PPDU"},
184 {REASON_ACA_PPDU,"aca PPDU"},
185 {REASON_TD_PPDU,"td PPDU"},
186 {REASON_TTD_PPDU,"td PPDU"},
187 {REASON_TE_PPDU,"te PPDU"},
188 {REASON_TC_PPDU,"tc PPDU"},
189 {REASON_TCC_PPDU,"tcc PPDU"},
190 {REASON_RS_PPDU,"rs PPDU"},
191 {REASON_RSA_PPDU,"rsa PPDU"},
192 {S_RELEASE_INDICATION,"s release indication"},
193 {S_RELEASE_CONFIRM,"s release confirm"},
194 {S_TOKEN_GIVE_INDICATION,"s token give indication"},
195 {S_TOKEN_PLEASE_INDICATION,"s token please indication"},
196 {S_CONTROL_GIVE_INDICATION,"s control give indication"},
197 {S_SYNC_MINOR_INDICATION,"s sync minor indication"},
198 {S_SYNC_MINOR_CONFIRM,"s sync minor confirm"},
199 {S_SYNC_MAJOR_INDICATION,"s sync major indication"},
200 {S_SYNC_MAJOR_CONFIRM,"s sync major confirm"},
201 {S_P_EXCEPTION_REPORT_INDICATION,"s p exception report indication"},
202 {S_U_EXCEPTION_REPORT_INDICATION,"s u exception report indication"},
203 {S_ACTIVITY_START_INDICATION,"s activity start indication"},
204 {S_ACTIVITY_RESUME_INDICATION,"s activity resume indication"},
205 {S_ACTIVITY_INTERRUPT_INDICATION,"s activity interrupt indication"},
206 {S_ACTIVITY_INTERRUPT_CONFIRM,"s activity interrupt confirm"},
207 {S_ACTIVITY_DISCARD_INDICATION,"s activity discard indication"},
208 {S_ACTIVITY_DISCARD_CONFIRM,"s activity discard confirm"},
209 {S_ACTIVITY_END_INDICATION,"s activity end indication"},
210 {S_ACTIVITY_END_CONFIRM,"s activity end confirm"},
213 /* pointers for acse dissector */
214 proto_tree *global_tree = NULL;
215 packet_info *global_pinfo = NULL;
216 /* dissector for data */
217 static dissector_handle_t data_handle;
220 call_acse_dissector(tvbuff_t *tvb, gint offset, gint param_len,
221 packet_info *pinfo, proto_tree *tree, proto_tree *param_tree)
223 /* do we have OSI acse/rose packet dissector ? */
226 /* No - display as data */
229 proto_tree_add_text(param_tree, tvb, offset, param_len,
230 "No ACSE dissector available");
235 /* Yes - call app dissector */
238 next_tvb = tvb_new_subset(tvb, offset, param_len, param_len);
241 call_dissector(acse_handle, next_tvb, pinfo, tree);
245 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
251 static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
254 gboolean def = FALSE;
255 int start = a->offset;
258 ret = asn1_length_decode(a, &def, &length);
259 if (ret != ASN1_ERR_NOERROR)
263 proto_tree_add_text(tree, a->tvb, start, 0,
264 "%s: ERROR: Couldn't parse length: %s",
265 proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
274 proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start,
277 return ASN1_ERR_NOERROR;
279 static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
280 proto_item **new_item, guint *i, int start, guint length)
283 proto_item *temp_item = NULL;
286 ret = asn1_uint32_value_decode(a, length, &integer);
287 if (ret != ASN1_ERR_NOERROR)
291 proto_tree_add_text(tree, a->tvb, start, 0,
292 "%s: ERROR: Couldn't parse value: %s",
293 proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
302 temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start,
303 a->offset-start, integer);
306 *new_item = temp_item;
308 return ASN1_ERR_NOERROR;
311 static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
312 proto_item **new_item, guint *i)
317 int start = a->offset;
320 ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
321 if (ret != ASN1_ERR_NOERROR)
325 proto_tree_add_text(tree, a->tvb, start, 0,
326 "%s: ERROR: Couldn't parse header: %s",
327 (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
328 asn1_err_to_str(ret));
333 return read_integer_value(a, tree, hf_id, new_item, i, start, length);
335 /* display asn.1 Integer type */
337 show_integer(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
338 *offset,int item_len)
340 proto_tree *pres_tree_itm = NULL;
343 int save_len = item_len;
345 itm = proto_tree_add_text(pres_tree, tvb, *offset, item_len,
347 pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
348 ret = read_integer(asn,pres_tree_itm,0,NULL,&item_len);
349 if (ret == ASN1_ERR_NOERROR )
351 *offset = asn->offset;
352 itm = proto_tree_add_text(pres_tree_itm, tvb, (*offset)-item_len,
354 "Integer value: %u",item_len);
358 /* can't dissect item. Skip it. */
359 *offset = off+ save_len;
364 show_presentation_requirements(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
365 *tvb,int *offset,int item_len,int tag)
367 proto_tree *pres_tree_itm = NULL;
371 /* do we have enough bytes to dissect this item ? */
372 if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
373 (asn->offset -*offset)+ item_len )
375 proto_tree_add_text(pres_tree, tvb, *offset, item_len,
376 "Wrong Item.Need %u bytes but have %u", item_len,length);
380 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
382 val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
383 pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
384 *offset = asn->offset;
385 flags = tvb_get_ntohs(tvb, *offset);
386 proto_tree_add_boolean(pres_tree_itm,hf_context_management, tvb, *offset,
388 proto_tree_add_boolean(pres_tree_itm,hf_restoration, tvb, *offset, 2,
390 *offset = *offset + item_len;
391 asn->offset = *offset;
395 show_protocol_version(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
396 *offset,int item_len,int tag)
398 proto_tree *pres_tree_itm = NULL;
402 /* do we have enough bytes to dissect this item ? */
403 if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
404 (asn->offset -*offset)+ item_len )
406 proto_tree_add_text(pres_tree, tvb, *offset, item_len,
407 "Wrong Item.Need %u bytes but have %u", item_len,length);
411 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
413 val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
414 pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
415 *offset = asn->offset;
416 flags = tvb_get_ntohs(tvb, *offset);
417 proto_tree_add_boolean(pres_tree_itm,hf_protocol_version, tvb, *offset,
419 *offset = *offset + item_len;
420 asn->offset = *offset;
423 print_oid_value(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
424 *offset,int item_len)
429 gchar *display_string;
433 ret = asn1_oid_value_decode (asn, item_len, &oid, &len);
434 if (ret != ASN1_ERR_NOERROR)
438 length = asn->offset - start;
439 display_string = format_oid(oid, len);
440 proto_tree_add_text(pres_tree, tvb, *offset,length,"Value:%s",
442 g_free(display_string);
443 (*offset)=start+item_len;
444 asn->offset = (*offset);
447 print_oid(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int *offset,int
454 gchar *display_string;
458 ret = asn1_oid_decode ( asn, &oid, &len, &nbytes);
460 if (ret != ASN1_ERR_NOERROR)
464 length = asn->offset - start;
465 display_string = format_oid(oid, len);
466 proto_tree_add_text(pres_tree, tvb, *offset,length,"Value:%s",
468 g_free(display_string);
469 (*offset)=start+item_len;
470 asn->offset = (*offset);
474 print_value(ASN1_SCK *asn,proto_tree *pres_tree, tvbuff_t *tvb, int *offset, int item_len)
476 gint start = *offset;
479 *offset = asn->offset; /* align to data*/
480 tmp = tvb_bytes_to_str(tvb, *offset, item_len);
481 proto_tree_add_text(pres_tree, tvb, *offset, item_len, tmp);
482 (*offset) = start+item_len;
483 asn->offset = (*offset);
487 get_integer_value(ASN1_SCK *asn,int length,int *offset)
490 int asn_off = asn->offset;
495 ret = asn1_uint32_value_decode(asn, length, &item_len);
496 /* return to present position */
498 asn->offset = asn_off;
500 if (ret != ASN1_ERR_NOERROR )
511 show_presentation_context_definition_result_seq(ASN1_SCK *asn,proto_tree
512 *pres_tree,tvbuff_t *tvb,int *offset,int item_len)
514 proto_tree *pres_tree_ms = NULL;
519 guint start = *offset;
524 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
526 old_offset = *offset ;
528 type = tvb_get_guint8(tvb, *offset);
531 asn->offset = *offset;
533 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
535 (*offset)=start+item_len;
536 asn->offset = (*offset);
540 /* do we have enough bytes to dissect ? */
541 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
544 proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
545 "Wrong item.Need %u bytes but have %u", new_item_len,length);
546 (*offset)=start+item_len;
547 asn->offset = (*offset);
550 header_len = asn->offset - (*offset) +1;
551 ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
552 new_item_len+(asn->offset-*offset)+1,
553 val_to_str(type, sequence_list_result_vals,
554 "Unknown item (0x%02x)"));
555 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
556 *offset = asn->offset;
561 case PRESENTATION_RESULT:
563 proto_tree *pres_tree_pr = NULL;
565 int value = get_integer_value(asn,new_item_len,offset);
566 pr = proto_tree_add_text(pres_tree_ms, tvb, *offset,
567 new_item_len+(asn->offset-*offset),
568 val_to_str(value ,sequence_list_result_values_vals,
569 "Unknown item (0x%02x)"));
570 pres_tree_pr = proto_item_add_subtree(pr, ett_pres_ms);
572 print_value(asn,pres_tree_pr,tvb,offset,new_item_len);
575 case PRESENTATION_RESULT_INTEGER:
576 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
578 case PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME:
579 print_oid_value(asn,pres_tree_ms,tvb,offset,new_item_len);
583 proto_tree_add_text(pres_tree, tvb, *offset,
584 new_item_len+(asn->offset-*offset),
585 "Unknown asn.1 parameter: (0x%02x)", type);
587 *offset = old_offset+new_item_len+header_len;
588 item_len-=new_item_len+header_len;
590 /* align the pointer */
591 (*offset)=start+item_len;
592 asn->offset = (*offset);
596 show_presentation_context_definition_seq(ASN1_SCK *asn,proto_tree
597 *pres_tree,tvbuff_t *tvb,int *offset,int item_len)
599 proto_tree *pres_tree_ms = NULL;
604 guint start = *offset;
609 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
611 old_offset = *offset ;
613 type = tvb_get_guint8(tvb, *offset);
616 asn->offset = *offset;
618 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
620 (*offset)=start+item_len;
621 asn->offset = (*offset);
625 /* do we have enough bytes to dissect ? */
626 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
629 proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
630 "Wrong item.Need %u bytes but have %u", new_item_len,length);
631 (*offset)=start+item_len;
632 asn->offset = (*offset);
635 header_len = asn->offset - (*offset) +1;
636 ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
637 new_item_len+(asn->offset-*offset)+1,
638 val_to_str(type, sequence_list_vals,
639 "Unknown item (0x%02x)"));
640 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
641 *offset = asn->offset;
646 case PRESENTATION_CONTEXT_IDENTIFIER:
647 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
649 case ABSTRACT_SYNTAX_NAME:
650 print_oid_value(asn,pres_tree_ms,tvb,offset,new_item_len);
652 case TRANSFER_SYNTAX_NAMES:
653 print_oid(asn,pres_tree_ms,tvb,offset,new_item_len);
656 proto_tree_add_text(pres_tree, tvb, *offset,
657 new_item_len+(asn->offset-*offset),
658 "Unknown asn.1 parameter: (0x%02x)", type);
660 *offset = old_offset+new_item_len+header_len;
661 item_len-=new_item_len+header_len;
663 /* align the pointer */
664 (*offset)=start+item_len;
665 asn->offset = (*offset);
668 show_fully_encoded_seq(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
669 *offset,int item_len)
671 proto_tree *pres_tree_ms = NULL;
676 guint start = *offset;
678 guint acse = 0; /* no acse id */
681 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
683 old_offset = *offset ;
685 type = tvb_get_guint8(tvb, *offset);
688 asn->offset = *offset;
690 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
692 (*offset)=start+item_len;
693 asn->offset = (*offset);
696 /* do we have enough bytes to dissect ? */
697 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
700 proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
701 "Wrong item.Need %u bytes but have %u", new_item_len,length);
702 (*offset)=start+item_len;
703 asn->offset = (*offset);
706 if(!new_item_len && length>2)
708 new_item_len = length-1; /* can't get length from asn1 tag. Use rest of the pdu len. */
710 header_len = asn->offset - (*offset) +1;
711 ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
712 new_item_len+(asn->offset-*offset)+1,
713 val_to_str(type, presentation_data_values,
714 "Unknown item (0x%02x)"));
715 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
716 *offset = asn->offset;
721 case PRESENTATION_CONTEXT_IDENTIFIER:
723 acse = get_integer_value(asn,new_item_len,offset);
724 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
726 session->pres_ctx_id=acse;
734 /* yes, we have to call ACSE dissector */
735 acse_ms = proto_tree_add_text(pres_tree_ms, tvb, *offset,new_item_len+(asn->offset-*offset),
738 session->abort_type = DATA_BLOCK;
739 /* call acse dissector */
740 call_acse_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,pres_tree_ms);
743 case SINGLE_ASN1_TYPE:
747 /* yes, we have to call ACSE dissector */
748 acse_ms = proto_tree_add_text(pres_tree_ms, tvb, *offset,
749 new_item_len+(asn->offset-*offset),
751 /* call acse dissector */
752 call_acse_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,pres_tree_ms);
757 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
760 proto_tree_add_text(pres_tree, tvb, *offset,
761 new_item_len+(asn->offset-*offset),
762 "Unknown asn.1 parameter: (0x%02x)", type);
764 *offset = old_offset+new_item_len+header_len;
765 item_len-=new_item_len+header_len;
767 /* align the pointer */
768 (*offset)=start+item_len;
769 asn->offset = (*offset);
773 show_fully_encoded_data(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
774 *tvb,int *offset,int item_len)
776 proto_tree *pres_tree_ms = NULL;
777 proto_tree *pres_tree_pc = NULL;
783 guint start = asn->offset;
784 guint item_length = item_len;
785 pres_tree_pc = pres_tree;
787 /* do we have enough bytes to dissect ? */
788 if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
790 proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
791 "Wrong item.Need %u bytes but have %u", item_len,length);
792 /* align the pointer */
793 (*offset)=start+item_length;
794 asn->offset = (*offset);
797 *offset =asn->offset;
800 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
802 int old_offset = *offset;
804 type = tvb_get_guint8(tvb, *offset);
807 asn->offset = *offset;
809 if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
812 /* align the pointer */
813 (*offset)=start+item_length;
814 asn->offset = (*offset);
817 header_len = asn->offset - (*offset) +1;
818 /* do we have enough bytes to dissect ? */
819 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
822 proto_tree_add_text(pres_tree_pc, tvb, *offset, new_item_len,
823 "Wrong item.Need %u bytes but have %u", new_item_len,length);
824 /* align the pointer */
825 (*offset)=start+item_length;
826 asn->offset = (*offset);
829 if(!new_item_len && length>2)
831 /* check if really do have what to dissect */
832 new_item_len = length-1;
834 ms = proto_tree_add_text(pres_tree_pc, tvb, *offset-1,
835 new_item_len+(asn->offset-*offset)+1,
836 val_to_str(type, presentation_context_definition_vals,
837 "Unknown item (0x%02x)"));
838 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
839 *offset = asn->offset;
846 show_fully_encoded_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
847 *offset = old_offset+(new_item_len+header_len);
851 proto_tree_add_text(pres_tree_ms, tvb, *offset,
852 new_item_len+(asn->offset-*offset),
853 "Unknown asn.1 parameter: (0x%02x)", type);
854 *offset = old_offset+(new_item_len+header_len);
856 item_len = item_len - (new_item_len+header_len);
861 /* align the pointer */
862 (*offset)=start+item_length;
863 asn->offset = (*offset);
866 show_session_provider_abort(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
867 *tvb,int *offset,int item_len)
871 proto_tree *pres_tree_pc = NULL;
872 proto_tree *pres_tree_pp = NULL;
877 /* do we have enough bytes to dissect this item ? */
878 if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
880 proto_tree_add_text(pres_tree, tvb, *offset, item_len,
881 "Wrong Item.Need %u bytes but have %u", item_len,length);
882 *offset = asn->offset;
885 itu = proto_tree_add_text(pres_tree, tvb, *offset,item_len,
887 pres_tree_pp = proto_item_add_subtree(itu, ett_pres_ms);
891 proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
892 "Provider reason not specified");
893 *offset = asn->offset;
896 itu = proto_tree_add_text(pres_tree_pp, tvb, *offset,ABORT_REASON_LEN,
898 pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
899 (*offset)++; /* skip type */
900 asn->offset = *offset;
903 if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
906 *offset = asn->offset;
909 /* try to get Abort reason */
910 value = get_integer_value(asn,new_item_len,offset);
913 proto_tree_add_text(pres_tree_pc, tvb, *offset+1,new_item_len,
914 val_to_str(value, provider_abort_values_vals,"Unknown item (0x%02x)"));
915 item_len-=(asn->offset-*offset)+new_item_len;
916 *offset = asn->offset+new_item_len;
917 asn->offset = *offset;
918 /* do we have Event identifier ? */
921 itu = proto_tree_add_text(pres_tree_pp, tvb, *offset,item_len,
923 pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
925 (*offset)++; /* skip type */
926 asn->offset = *offset;
929 if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
932 *offset = asn->offset;
935 /* try to get Event identifier */
936 value = get_integer_value(asn,new_item_len,offset);
938 proto_tree_add_text(pres_tree_pc, tvb, *offset+1,new_item_len,
939 val_to_str(value, event_identifier_values_vals,"Unknown item (0x%02x)"));
940 item_len-=(asn->offset-*offset)+new_item_len;
941 *offset = asn->offset+new_item_len;
942 asn->offset = *offset;
946 show_user_data(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
947 *offset,int item_len,int tag)
949 proto_tree *pres_tree_ud = NULL;
950 proto_tree *pres_tree_pc = NULL;
953 guint start = asn->offset;
954 guint item_length = item_len;
956 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
957 item_len, "User data");
958 pres_tree_ud = proto_item_add_subtree(itm, ett_pres_ms);
959 itu = proto_tree_add_text(pres_tree_ud, tvb,
960 *offset,item_len+(asn->offset-*offset),
961 val_to_str(tag, user_data_values_vals,"Unknown item (0x%02x)"));
962 pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
965 case SIMPLY_ENCODED_DATA:
967 case FULLY_ENCODED_DATA:
968 show_fully_encoded_data(asn,pres_tree_pc,tvb,offset,item_len);
975 /* align the pointer */
976 (*offset)=start+item_length;
977 asn->offset = (*offset);
982 show_presentation_context_definition(ASN1_SCK *asn,proto_tree
983 *pres_tree,tvbuff_t *tvb,int *offset,int item_len,int tag)
985 proto_tree *pres_tree_ms = NULL;
986 proto_tree *pres_tree_pc = NULL;
993 guint start = asn->offset;
994 guint item_length = item_len;
996 itm = proto_tree_add_text(pres_tree, tvb,
997 *offset,item_len+(asn->offset-*offset),
998 val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
999 pres_tree_pc = proto_item_add_subtree(itm, ett_pres_ms);
1001 /* do we have enough bytes to dissect ? */
1002 if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
1004 proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
1005 "Wrong item.Need %u bytes but have %u", item_len,length);
1006 /* align the pointer */
1007 (*offset)=start+item_length;
1008 asn->offset = (*offset);
1011 *offset =asn->offset;
1014 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
1016 int old_offset = *offset;
1018 type = tvb_get_guint8(tvb, *offset);
1021 asn->offset = *offset;
1023 if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
1026 /* align the pointer */
1027 (*offset)=start+item_length;
1028 asn->offset = (*offset);
1031 header_len = asn->offset - (*offset) +1;
1032 /* do we have enough bytes to dissect ? */
1033 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
1036 proto_tree_add_text(pres_tree_pc, tvb, *offset, new_item_len,
1037 "Wrong item.Need %u bytes but have %u", new_item_len,length);
1038 /* align the pointer */
1039 (*offset)=start+item_length;
1040 asn->offset = (*offset);
1043 ms = proto_tree_add_text(pres_tree_pc, tvb, *offset-1,
1044 new_item_len+(asn->offset-*offset)+1,
1045 val_to_str(type, presentation_context_definition_vals,
1046 "Unknown item (0x%02x)"));
1047 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1048 *offset = asn->offset;
1055 if(tag == PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST
1056 || tag == DEFAULT_CONTEXT_RESULT)
1058 show_presentation_context_definition_result_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
1062 show_presentation_context_definition_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
1064 *offset = old_offset+(new_item_len+header_len);
1068 proto_tree_add_text(pres_tree_ms, tvb, *offset,
1069 new_item_len+(asn->offset-*offset),
1070 "Unknown asn.1 parameter: (0x%02x)", type);
1071 *offset = old_offset+(new_item_len+header_len);
1073 item_len = item_len - (new_item_len+header_len);
1078 /* align the pointer */
1079 (*offset)=start+item_length;
1080 asn->offset = (*offset);
1082 /* if we can't dissect */
1084 dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
1085 proto_tree *tree, const char *field_name, int ret)
1088 errstr = asn1_err_to_str(ret);
1092 proto_tree_add_text(tree, tvb, offset, 0,
1093 "ERROR: Couldn't parse %s: %s", field_name, errstr);
1094 call_dissector(data_handle,
1095 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
1099 static int read_string_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
1100 proto_item **new_item, char **s, int start, guint length)
1103 proto_item *temp_item = NULL;
1108 ret = asn1_string_value_decode(a, length, &string);
1109 if (ret != ASN1_ERR_NOERROR)
1113 proto_tree_add_text(tree, a->tvb, start, 0,
1114 "%s: ERROR: Couldn't parse value: %s",
1115 proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
1119 string = g_realloc(string, length + 1);
1120 string[length] = '\0';
1126 temp_item = proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset
1129 *new_item = temp_item;
1136 return ASN1_ERR_NOERROR;
1139 show_provider_reason(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
1140 *offset,int item_len,int type)
1144 proto_tree *pres_tree_ms = NULL;
1145 proto_tree *pres_tree_pr = NULL;
1148 int new_item_len = item_len+(asn->offset-*offset);
1150 ms = proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
1151 val_to_str(type, sequence_top_vals,
1152 "Unknown item (0x%02x)"));
1153 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1154 value = get_integer_value(asn,item_len,offset);
1155 pr = proto_tree_add_text(pres_tree_ms, tvb, *offset, new_item_len,
1156 val_to_str(value, provider_reason_values_vals,
1157 "Unknown item (0x%02x)"));
1158 pres_tree_pr = proto_item_add_subtree(pr, ett_pres_ms);
1159 print_value(asn,pres_tree_pr,tvb,offset,item_len);
1160 asn->offset = *offset = off+new_item_len;
1163 show_presentation_selector (ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
1164 *tvb,int *offset,int item_len,int type)
1167 proto_tree *pres_tree_ms = NULL;
1171 ms = proto_tree_add_text(pres_tree, tvb, *offset,
1172 item_len+(asn->offset-*offset),
1173 val_to_str(type, sequence_top_vals,
1174 "Unknown item (0x%02x)"));
1177 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1179 ret = read_string_value(asn, pres_tree,0,NULL, &s,
1180 *offset+(asn->offset-*offset), item_len);
1181 if(ret == ASN1_ERR_NOERROR)
1185 proto_tree_add_text(pres_tree_ms, tvb, *offset+2, item_len,
1191 proto_tree_add_text(pres_tree_ms, tvb, *offset+2, item_len,
1192 "Zero selector length");
1200 /* display top sequence */
1202 show_sequence_top(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
1203 *tvb,packet_info *pinfo,int *offset,int item_len)
1206 guint cls, con, tag,len1;
1211 while(item_len > 0 )
1213 /* do we have enough bytes to dissect this item ? */
1214 if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
1216 proto_tree_add_text(pres_tree, tvb, *offset, item_len,
1217 "Wrong Item.Need %u bytes but have %u", item_len,length);
1221 type = tvb_get_guint8(tvb, *offset);
1223 ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
1225 if (ret != ASN1_ERR_NOERROR)
1227 dissect_parse_error(tvb, *offset, pinfo, pres_tree,
1228 "sequence error", ret);
1231 item_len = item_len - (asn->offset - *offset);
1233 * [APPLICATION <tag>]
1238 /* Calling-presentation-selector and
1239 User data have the same tag number
1240 Try to recognize which one do we really have */
1241 if( con == ASN1_CON)
1243 /* it is User data */
1245 show_user_data(asn,pres_tree,tvb,offset,len1,type);
1248 /* it is Calling-presentation-selector */
1249 /* simply go below, we don't need to break here */
1251 case CALLED_PRESENTATION_SELECTOR:
1252 case RESPONDING_PRESENTATION_SELECTOR:
1253 /*case CALLING_PRESENTATION_SELECTOR:*/
1255 * [Called-presentation-selector]
1256 * [Calling-presentation-selector]
1257 * [Responding-presentation-selector]
1259 show_presentation_selector(asn,pres_tree,tvb,offset,len1,tag);
1261 case DEFAULT_CONTEXT_NAME:
1262 case PRESENTATION_CONTEXT_DEFINITION_LIST:
1263 show_presentation_context_definition(asn,pres_tree,tvb,offset,len1,tag);
1265 case PROTOCOL_VERSION:
1269 /* yes, it is application */
1270 *offset = asn->offset;
1274 show_protocol_version(asn,pres_tree,tvb,offset,len1,tag);
1276 case PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST:
1277 case DEFAULT_CONTEXT_RESULT:
1278 show_presentation_context_definition(asn,pres_tree,tvb,offset,len1,tag);
1280 case PRESENTATION_REQUIREMENTS:
1281 show_presentation_requirements(asn,pres_tree,tvb,offset,len1,tag);
1283 case PROVIDER_REASON:
1284 show_provider_reason(asn,pres_tree,tvb,offset,len1,tag);
1288 case USER_SESSION_REQUIREMENTS:
1290 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset
1292 val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
1293 (asn->offset)+=len1;
1297 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset
1299 "Unknown tag: %x",tag);
1300 (asn->offset)+=len1;
1304 *offset = asn->offset;
1309 show_connection_request_confirm(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
1310 *tvb,packet_info *pinfo,int *offset,int* item_len)
1314 proto_tree *pres_tree_ms = NULL;
1316 /* get type of set */
1317 while ( tvb_reported_length_remaining(tvb, *offset) > 0 )
1321 type = tvb_get_guint8(tvb, *offset);
1322 asn1_tag = type & 0x1f;
1325 asn->offset = *offset;
1327 if (read_length(asn, pres_tree, 0, item_len) != ASN1_ERR_NOERROR)
1331 /* do we have enough bytes to dissect ? */
1332 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
1335 proto_tree_add_text(pres_tree, tvb, *offset, -1,
1336 "Wrong item.Need %u bytes but have %u", *item_len,length);
1339 ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
1340 *item_len+(asn->offset-*offset)+1,
1341 val_to_str(asn1_tag, cr_vals,
1342 "Unknown item (0x%02x)"));
1343 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1348 proto_tree_add_uint(pres_tree_ms, hf_pres_ms_type, tvb, (*offset)-1, 1,
1350 proto_tree_add_text(pres_tree_ms, tvb, *offset, (asn->offset-*offset),
1351 "Length:%u",*item_len);
1352 *offset=asn->offset;
1353 show_integer(asn,pres_tree_ms,tvb,offset,*item_len);
1357 proto_tree_add_uint(pres_tree_ms, hf_pres_seq_type, tvb, (*offset)-1, 1,
1359 proto_tree_add_text(pres_tree_ms, tvb, *offset, (asn->offset-*offset),
1360 "Length:%u",*item_len);
1361 *offset=asn->offset;
1362 show_sequence_top(asn,pres_tree_ms,tvb,pinfo,offset,*item_len);
1365 proto_tree_add_text(pres_tree, tvb, (*offset)-1,
1366 *item_len+(asn->offset-*offset)+1,
1367 "Unknown asn.1 parameter: (0x%02x).Tag :(0x%02x)", type,asn1_tag);
1368 (*offset)+=*item_len+(asn->offset-*offset);
1369 asn->offset = *offset;
1380 dissect_ppdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
1384 proto_tree *pres_tree = NULL;
1390 /* do we have spdu type from the session dissector? */
1391 if( !pinfo->private_data )
1395 proto_tree_add_text(tree, tvb, offset, -1,
1396 "Internal error:can't get spdu type from session dissector.");
1402 session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
1403 if(session->spdu_type == 0 )
1407 proto_tree_add_text(tree, tvb, offset, -1,
1408 "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
1413 /* get type of tag */
1414 s_type = tvb_get_guint8(tvb, offset);
1415 /* set up type of Ppdu */
1416 if (check_col(pinfo->cinfo, COL_INFO))
1417 col_add_str(pinfo->cinfo, COL_INFO,
1418 val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
1421 ti = proto_tree_add_item(tree, proto_pres, tvb, offset, -1,
1423 pres_tree = proto_item_add_subtree(ti, ett_pres);
1426 /* open asn.1 stream */
1427 asn1_open(&asn, tvb, offset);
1429 switch(session->spdu_type)
1432 proto_tree_add_uint(pres_tree, hf_pres_type, tvb, offset-1, 1, s_type);
1433 if (read_length(&asn, pres_tree, hf_cp_type_message_length, &cp_type_len)
1434 != ASN1_ERR_NOERROR)
1439 offset = asn.offset;
1440 /* do we have enough bytes to dissect ? */
1441 if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
1446 proto_tree_add_text(pres_tree, tvb, offset, -1,
1447 "Wrong Ppdu.Need %u bytes but have %u", cp_type_len,length);
1452 asn.offset = offset;
1453 show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,cp_type_len);
1457 case SES_CONNECTION_REQUEST:
1458 case SES_CONNECTION_ACCEPT:
1459 proto_tree_add_uint(pres_tree, hf_pres_type, tvb, offset-1, 1, s_type);
1461 if (read_length(&asn, pres_tree, hf_cp_type_message_length, &cp_type_len)
1462 != ASN1_ERR_NOERROR)
1467 offset = asn.offset;
1468 /* do we have enough bytes to dissect ? */
1469 if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
1474 proto_tree_add_text(pres_tree, tvb, offset, -1,
1475 "Wrong Ppdu.Need %u bytes but have %u", cp_type_len,length);
1480 show_connection_request_confirm(&asn,pres_tree,tvb,pinfo,&offset,&cp_type_len);
1485 if (read_length(&asn, pres_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1490 offset = asn.offset;
1491 /* do we have enough bytes to dissect ? */
1492 if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
1496 proto_tree_add_text(pres_tree, tvb, offset, -1,
1497 "Wrong Ppdu.Need %u bytes but have %u", rest_len,length);
1501 if(session->abort_type == SESSION_USER_ABORT )
1504 if(s_type == ASN1_CLASS_PC+ASN1_CLASS_CONTEXT_SPECIFIC)
1508 show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,rest_len);
1516 show_session_provider_abort(&asn,pres_tree,tvb,&offset,rest_len);
1525 show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,rest_len);
1533 proto_tree *pres_tree_ms = NULL;
1534 /* back to length */
1537 if (read_length(&asn, pres_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1543 guint rest_pdu_len = 0;
1544 /* do we really haven't any more bytes ? */
1545 if( (rest_pdu_len = tvb_reported_length_remaining(tvb, offset)) )
1548 * we have but can't say how many from asn1 information.
1549 * use pdu len instead
1551 if(rest_pdu_len > 2)
1553 rest_len = rest_pdu_len;
1557 if( ((gint)rest_len) > 0) {
1558 ms = proto_tree_add_text(pres_tree, tvb, offset, rest_len,
1559 val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
1560 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1561 show_user_data(&asn,pres_tree_ms,tvb,&offset,rest_len,s_type);
1565 /* close asn.1 stream */
1566 asn1_close(&asn, &offset);
1572 * Dissect PPDUs inside a SPDU.
1575 dissect_pres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1578 /* first, try to check length */
1579 /* do we have at least 4 bytes */
1580 if (!tvb_bytes_exist(tvb, 0, 4))
1582 proto_tree_add_text(tree, tvb, offset, tvb_reported_length_remaining(tvb,
1585 return; /* no, it isn't a presentation PDU */
1588 /* we can't make any additional checking here */
1589 /* postpone it before dissector will have more information */
1591 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1592 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRES");
1593 if (check_col(pinfo->cinfo, COL_INFO))
1594 col_clear(pinfo->cinfo, COL_INFO);
1595 /* save pointers for calling the acse dissector */
1597 global_pinfo = pinfo;
1599 while (tvb_reported_length_remaining(tvb, offset) > 0)
1601 offset = dissect_ppdu(tvb, offset, pinfo, tree);
1602 if(offset == FALSE )
1604 proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
1605 offset = tvb_length(tvb);
1612 proto_register_pres(void)
1614 static hf_register_info hf[] =
1641 &hf_cp_type_message_length,
1644 "cp_type.message_length",
1649 "CP type Message Length",
1656 "Connection reqiest/confirm",
1662 "Connection reqiest/confirm",
1671 "pres.mode.selector",
1681 &hf_pres_protocol_version,
1684 "pres.protocol.version",
1722 &hf_protocol_version,
1724 "Protocol version 1",
1725 "pres.protocol.version",
1728 PRES_PROTOCOL_VERGION,
1729 "Protocol version 1",
1734 &hf_context_management,
1736 "Context management",
1737 "pres.context.management",
1740 PRES_CONTEXT_MANAGEMENT,
1741 "Context management",
1761 static gint *ett[] =
1769 module_t *pres_module;
1772 proto_pres = proto_register_protocol(PROTO_STRING_PRES, "PRES", "pres");
1773 proto_register_field_array(proto_pres, hf, array_length(hf));
1774 proto_register_subtree_array(ett, array_length(ett));
1776 pres_module = prefs_register_protocol(proto_pres, NULL);
1779 * Register the dissector by name, so other dissectors can
1780 * grab it by name rather than just referring to it directly
1781 * (you can't refer to it directly from a plugin dissector
1782 * on Windows without stuffing it into the Big Transfer Vector).
1784 register_dissector("pres", dissect_pres, proto_pres);
1788 proto_reg_handoff_pres(void)
1790 /* find data dissector */
1791 data_handle = find_dissector("data");
1792 /* define acse sub dissector */
1793 acse_handle = find_dissector("acse");