3 * Routine to dissect ISO 8823 OSI Presentation Protocol packets
5 * $Id: packet-pres.c,v 1.1 2004/01/13 02:10:25 guy Exp $
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"
42 #include <epan/strutil.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"},
164 static const value_string provider_abort_values_vals[] =
166 {PR_REASON_NOT_SPECIFIED,"Reason not specified"},
167 {UNRECOGNIZED_PDU,"Unrecognized ppdu"},
168 {UNEXPECTED_PDU,"Unexpected ppdu"},
169 {UNEXPECTED_SESSION_SERVICE_PRIMITIVE,"Unexpected session service primitive"},
170 {UNRECOGNIZED_PPDU_PARAMETER,"Unrecognized ppdu parameter"},
171 {UNEXPECTED_PPDU_PARAMETER,"Unexpected ppdu parameter"},
172 {INVALID_PPDU_PARAMETER_VALUE,"Invalid ppdu parameter value"},
175 static const value_string event_identifier_values_vals[] =
177 {REASON_CP_PPDU,"cp PPDU"},
178 {REASON_CPA_PPDU,"cpa PPDU"},
179 {REASON_CPR_PPDU,"cpr PPDU"},
180 {REASON_ARU_PPDU,"aru PPDU"},
181 {REASON_ARP_PPDU,"arp PPDU"},
182 {REASON_AC_PPDU,"ac PPDU"},
183 {REASON_ACA_PPDU,"aca PPDU"},
184 {REASON_TD_PPDU,"td PPDU"},
185 {REASON_TTD_PPDU,"td PPDU"},
186 {REASON_TE_PPDU,"te PPDU"},
187 {REASON_TC_PPDU,"tc PPDU"},
188 {REASON_TCC_PPDU,"tcc PPDU"},
189 {REASON_RS_PPDU,"rs PPDU"},
190 {REASON_RSA_PPDU,"rsa PPDU"},
191 {S_RELEASE_INDICATION,"s release indication"},
192 {S_RELEASE_CONFIRM,"s release confirm"},
193 {S_TOKEN_GIVE_INDICATION,"s token give indication"},
194 {S_TOKEN_PLEASE_INDICATION,"s token please indication"},
195 {S_CONTROL_GIVE_INDICATION,"s control give indication"},
196 {S_SYNC_MINOR_INDICATION,"s sync minor indication"},
197 {S_SYNC_MINOR_CONFIRM,"s sync minor confirm"},
198 {S_SYNC_MAJOR_INDICATION,"s sync major indication"},
199 {S_SYNC_MAJOR_CONFIRM,"s sync major confirm"},
200 {S_P_EXCEPTION_REPORT_INDICATION,"s p exception report indication"},
201 {S_U_EXCEPTION_REPORT_INDICATION,"s u exception report indication"},
202 {S_ACTIVITY_START_INDICATION,"s activity start indication"},
203 {S_ACTIVITY_RESUME_INDICATION,"s activity resume indication"},
204 {S_ACTIVITY_INTERRUPT_INDICATION,"s activity interrupt indication"},
205 {S_ACTIVITY_INTERRUPT_CONFIRM,"s activity interrupt confirm"},
206 {S_ACTIVITY_DISCARD_INDICATION,"s activity discard indication"},
207 {S_ACTIVITY_DISCARD_CONFIRM,"s activity discard confirm"},
208 {S_ACTIVITY_END_INDICATION,"s activity end indication"},
209 {S_ACTIVITY_END_CONFIRM,"s activity end confirm"},
212 /* pointers for acse dissector */
213 proto_tree *global_tree = NULL;
214 packet_info *global_pinfo = NULL;
215 /* dissector for data */
216 static dissector_handle_t data_handle;
219 call_acse_dissector(tvbuff_t *tvb, int offset, guint16 param_len,
220 packet_info *pinfo, proto_tree *tree, proto_tree *param_tree)
222 /* do we have OSI acse/rose packet dissector ? */
225 /* No - display as data */
228 proto_tree_add_text(param_tree, tvb, offset, param_len,
229 "No ACSE dissector available");
233 /* Yes - call app dissector */
236 next_tvb = tvb_new_subset(tvb, offset, param_len,
240 call_dissector(acse_handle, next_tvb, pinfo,
245 show_exception(tvb, pinfo, tree, EXCEPT_CODE);
252 string_to_hex(unsigned char * in,char * out,int len)
254 char ascii[MAXSTRING];
256 memset(&ascii,0x00,sizeof(ascii));
259 unsigned char o_out = *(in+i);
260 sprintf(out+(i<<1),"%.2x",* (in+i));
261 if( ( (o_out) >= 'a') & ( (o_out) <='z') ||
262 ( (o_out) >= 'A') & ( (o_out) <='Z') ||
263 ( (o_out) >= '0') & ( (o_out) <='9')
279 static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
282 gboolean def = FALSE;
283 int start = a->offset;
286 ret = asn1_length_decode(a, &def, &length);
287 if (ret != ASN1_ERR_NOERROR)
291 proto_tree_add_text(tree, a->tvb, start, 0,
292 "%s: ERROR: Couldn't parse length: %s",
293 proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
302 proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start,
305 return ASN1_ERR_NOERROR;
307 static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
308 proto_item **new_item, guint *i, int start, guint length)
311 proto_item *temp_item = NULL;
314 ret = asn1_uint32_value_decode(a, length, &integer);
315 if (ret != ASN1_ERR_NOERROR)
319 proto_tree_add_text(tree, a->tvb, start, 0,
320 "%s: ERROR: Couldn't parse value: %s",
321 proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
330 temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start,
331 a->offset-start, integer);
334 *new_item = temp_item;
336 return ASN1_ERR_NOERROR;
339 static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
340 proto_item **new_item, guint *i)
345 int start = a->offset;
348 ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
349 if (ret != ASN1_ERR_NOERROR)
353 proto_tree_add_text(tree, a->tvb, start, 0,
354 "%s: ERROR: Couldn't parse header: %s",
355 (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
356 asn1_err_to_str(ret));
361 return read_integer_value(a, tree, hf_id, new_item, i, start, length);
363 /* display asn.1 Integer type */
365 show_integer(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
366 *offset,int item_len)
368 proto_tree *pres_tree_itm = NULL;
371 int save_len = item_len;
373 itm = proto_tree_add_text(pres_tree, tvb, *offset, item_len,
375 pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
376 ret = read_integer(asn,pres_tree_itm,0,NULL,&item_len);
377 if (ret == ASN1_ERR_NOERROR )
379 *offset = asn->offset;
380 itm = proto_tree_add_text(pres_tree_itm, tvb, (*offset)-item_len,
382 "Integer value: %u",item_len);
386 /* can't dissect item. Skip it. */
387 *offset = off+ save_len;
392 show_presentation_requirements(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
393 *tvb,int *offset,int item_len,int tag)
395 proto_tree *pres_tree_itm = NULL;
399 /* do we have enough bytes to dissect this item ? */
400 if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
401 (asn->offset -*offset)+ item_len )
403 proto_tree_add_text(pres_tree, tvb, *offset, item_len,
404 "Wrong Item.Need %u bytes but have %u", item_len,length);
408 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
410 val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
411 pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
412 *offset = asn->offset;
413 flags = tvb_get_ntohs(tvb, *offset);
414 proto_tree_add_boolean(pres_tree_itm,hf_context_management, tvb, *offset,
416 proto_tree_add_boolean(pres_tree_itm,hf_restoration, tvb, *offset, 2,
418 *offset = *offset + item_len;
419 asn->offset = *offset;
423 show_protocol_version(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
424 *offset,int item_len,int tag)
426 proto_tree *pres_tree_itm = NULL;
430 /* do we have enough bytes to dissect this item ? */
431 if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
432 (asn->offset -*offset)+ item_len )
434 proto_tree_add_text(pres_tree, tvb, *offset, item_len,
435 "Wrong Item.Need %u bytes but have %u", item_len,length);
439 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
441 val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
442 pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
443 *offset = asn->offset;
444 flags = tvb_get_ntohs(tvb, *offset);
445 proto_tree_add_boolean(pres_tree_itm,hf_protocol_version, tvb, *offset,
447 *offset = *offset + item_len;
448 asn->offset = *offset;
451 print_oid_value(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
452 *offset,int item_len)
457 gchar *display_string;
461 ret = asn1_oid_value_decode (asn, item_len, &oid, &len);
462 if (ret != ASN1_ERR_NOERROR)
466 length = asn->offset - start;
467 display_string = format_oid(oid, len);
468 proto_tree_add_text(pres_tree, tvb, *offset,length,"Value:%s",
470 g_free(display_string);
471 (*offset)=start+item_len;
472 asn->offset = (*offset);
475 print_oid(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int *offset,int
482 gchar *display_string;
486 ret = asn1_oid_decode ( asn, &oid, &len, &nbytes);
488 if (ret != ASN1_ERR_NOERROR)
492 length = asn->offset - start;
493 display_string = format_oid(oid, len);
494 proto_tree_add_text(pres_tree, tvb, *offset,length,"Value:%s",
496 g_free(display_string);
497 (*offset)=start+item_len;
498 asn->offset = (*offset);
502 print_value(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
503 *offset,int item_len)
505 gint start = *offset;
507 *offset = asn->offset; /* align to data*/
508 string_to_hex((char*)tvb_get_ptr(tvb,*offset,item_len),tmp,item_len);
509 proto_tree_add_text(pres_tree, tvb, *offset, item_len, tmp);
510 (*offset)=start+item_len;
511 asn->offset = (*offset);
514 get_integer_value(ASN1_SCK *asn,int length,int *offset)
517 int asn_off = asn->offset;
522 ret = asn1_uint32_value_decode(asn, length, &item_len);
523 /* return to present position */
525 asn->offset = asn_off;
527 if (ret != ASN1_ERR_NOERROR )
538 show_presentation_context_definition_result_seq(ASN1_SCK *asn,proto_tree
539 *pres_tree,tvbuff_t *tvb,int *offset,int item_len)
541 proto_tree *pres_tree_ms = NULL;
546 guint start = *offset;
551 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
553 old_offset = *offset ;
555 type = tvb_get_guint8(tvb, *offset);
558 asn->offset = *offset;
560 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
562 (*offset)=start+item_len;
563 asn->offset = (*offset);
567 /* do we have enough bytes to dissect ? */
568 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
571 proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
572 "Wrong item.Need %u bytes but have %u", new_item_len,length);
573 (*offset)=start+item_len;
574 asn->offset = (*offset);
577 header_len = asn->offset - (*offset) +1;
578 ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
579 new_item_len+(asn->offset-*offset)+1,
580 val_to_str(type, sequence_list_result_vals,
581 "Unknown item (0x%02x)"));
582 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
583 *offset = asn->offset;
588 case PRESENTATION_RESULT:
590 proto_tree *pres_tree_pr = NULL;
592 int value = get_integer_value(asn,new_item_len,offset);
593 pr = proto_tree_add_text(pres_tree_ms, tvb, *offset,
594 new_item_len+(asn->offset-*offset),
595 val_to_str(value ,sequence_list_result_values_vals,
596 "Unknown item (0x%02x)"));
597 pres_tree_pr = proto_item_add_subtree(pr, ett_pres_ms);
599 print_value(asn,pres_tree_pr,tvb,offset,new_item_len);
602 case PRESENTATION_RESULT_INTEGER:
603 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
605 case PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME:
606 print_oid_value(asn,pres_tree_ms,tvb,offset,new_item_len);
610 proto_tree_add_text(pres_tree, tvb, *offset,
611 new_item_len+(asn->offset-*offset),
612 "Unknown asn.1 parameter: (0x%02x)", type);
614 *offset = old_offset+new_item_len+header_len;
615 item_len-=new_item_len+header_len;
617 /* align the pointer */
618 (*offset)=start+item_len;
619 asn->offset = (*offset);
623 show_presentation_context_definition_seq(ASN1_SCK *asn,proto_tree
624 *pres_tree,tvbuff_t *tvb,int *offset,int item_len)
626 proto_tree *pres_tree_ms = NULL;
631 guint start = *offset;
636 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
638 old_offset = *offset ;
640 type = tvb_get_guint8(tvb, *offset);
643 asn->offset = *offset;
645 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
647 (*offset)=start+item_len;
648 asn->offset = (*offset);
652 /* do we have enough bytes to dissect ? */
653 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
656 proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
657 "Wrong item.Need %u bytes but have %u", new_item_len,length);
658 (*offset)=start+item_len;
659 asn->offset = (*offset);
662 header_len = asn->offset - (*offset) +1;
663 ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
664 new_item_len+(asn->offset-*offset)+1,
665 val_to_str(type, sequence_list_vals,
666 "Unknown item (0x%02x)"));
667 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
668 *offset = asn->offset;
673 case PRESENTATION_CONTEXT_IDENTIFIER:
674 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
676 case ABSTRACT_SYNTAX_NAME:
677 print_oid_value(asn,pres_tree_ms,tvb,offset,new_item_len);
679 case TRANSFER_SYNTAX_NAMES:
680 print_oid(asn,pres_tree_ms,tvb,offset,new_item_len);
683 proto_tree_add_text(pres_tree, tvb, *offset,
684 new_item_len+(asn->offset-*offset),
685 "Unknown asn.1 parameter: (0x%02x)", type);
687 *offset = old_offset+new_item_len+header_len;
688 item_len-=new_item_len+header_len;
690 /* align the pointer */
691 (*offset)=start+item_len;
692 asn->offset = (*offset);
695 show_fully_encoded_seq(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
696 *offset,int item_len)
698 proto_tree *pres_tree_ms = NULL;
703 guint start = *offset;
705 guint acse = 0; /* no acse id */
708 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
710 old_offset = *offset ;
712 type = tvb_get_guint8(tvb, *offset);
715 asn->offset = *offset;
717 if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
719 (*offset)=start+item_len;
720 asn->offset = (*offset);
723 /* do we have enough bytes to dissect ? */
724 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
727 proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
728 "Wrong item.Need %u bytes but have %u", new_item_len,length);
729 (*offset)=start+item_len;
730 asn->offset = (*offset);
733 header_len = asn->offset - (*offset) +1;
734 ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
735 new_item_len+(asn->offset-*offset)+1,
736 val_to_str(type, presentation_data_values,
737 "Unknown item (0x%02x)"));
738 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
739 *offset = asn->offset;
744 case PRESENTATION_CONTEXT_IDENTIFIER:
746 /* if Presentation context identifier = 3 we have ACSE data */
747 /* this data we have to send to ACSE dissector */
748 acse = get_integer_value(asn,new_item_len,offset);
749 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
754 case SINGLE_ASN1_TYPE:
755 if( acse == ACSE_PRESENTATION_CONTEXT_IDENTIFIER )
758 /* yes, we have to call ACSE dissector */
759 acse_ms = proto_tree_add_text(pres_tree_ms, tvb, *offset,
760 new_item_len+(asn->offset-*offset),
762 /* call acse dissector */
763 call_acse_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,pres_tree_ms);
768 print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
771 proto_tree_add_text(pres_tree, tvb, *offset,
772 new_item_len+(asn->offset-*offset),
773 "Unknown asn.1 parameter: (0x%02x)", type);
775 *offset = old_offset+new_item_len+header_len;
776 item_len-=new_item_len+header_len;
778 /* align the pointer */
779 (*offset)=start+item_len;
780 asn->offset = (*offset);
784 show_fully_encoded_data(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
785 *tvb,int *offset,int item_len)
787 proto_tree *pres_tree_ms = NULL;
788 proto_tree *pres_tree_pc = NULL;
794 guint start = asn->offset;
795 guint item_length = item_len;
796 pres_tree_pc = pres_tree;
798 /* do we have enough bytes to dissect ? */
799 if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
801 proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
802 "Wrong item.Need %u bytes but have %u", item_len,length);
803 /* align the pointer */
804 (*offset)=start+item_length;
805 asn->offset = (*offset);
808 *offset =asn->offset;
811 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
813 int old_offset = *offset;
815 type = tvb_get_guint8(tvb, *offset);
818 asn->offset = *offset;
820 if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
823 /* align the pointer */
824 (*offset)=start+item_length;
825 asn->offset = (*offset);
828 header_len = asn->offset - (*offset) +1;
829 /* do we have enough bytes to dissect ? */
830 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
833 proto_tree_add_text(pres_tree_pc, tvb, *offset, new_item_len,
834 "Wrong item.Need %u bytes but have %u", new_item_len,length);
835 /* align the pointer */
836 (*offset)=start+item_length;
837 asn->offset = (*offset);
840 ms = proto_tree_add_text(pres_tree_pc, tvb, *offset-1,
841 new_item_len+(asn->offset-*offset)+1,
842 val_to_str(type, presentation_context_definition_vals,
843 "Unknown item (0x%02x)"));
844 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
845 *offset = asn->offset;
852 show_fully_encoded_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
853 *offset = old_offset+(new_item_len+header_len);
857 proto_tree_add_text(pres_tree_ms, tvb, *offset,
858 new_item_len+(asn->offset-*offset),
859 "Unknown asn.1 parameter: (0x%02x)", type);
860 *offset = old_offset+(new_item_len+header_len);
862 item_len = item_len - (new_item_len+header_len);
867 /* align the pointer */
868 (*offset)=start+item_length;
869 asn->offset = (*offset);
872 show_session_provider_abort(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
873 *tvb,int *offset,int item_len)
877 proto_tree *pres_tree_pc = NULL;
878 proto_tree *pres_tree_pp = NULL;
883 /* do we have enough bytes to dissect this item ? */
884 if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
886 proto_tree_add_text(pres_tree, tvb, *offset, item_len,
887 "Wrong Item.Need %u bytes but have %u", item_len,length);
888 *offset = asn->offset;
891 itu = proto_tree_add_text(pres_tree, tvb, *offset,item_len,
893 pres_tree_pp = proto_item_add_subtree(itu, ett_pres_ms);
897 proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
898 "Provider reason not specified");
899 *offset = asn->offset;
902 itu = proto_tree_add_text(pres_tree_pp, tvb, *offset,ABORT_REASON_LEN,
904 pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
905 (*offset)++; /* skip type */
906 asn->offset = *offset;
909 if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
912 *offset = asn->offset;
915 /* try to get Abort reason */
916 value = get_integer_value(asn,new_item_len,offset);
919 proto_tree_add_text(pres_tree_pc, tvb, *offset+1,new_item_len,
920 val_to_str(value, provider_abort_values_vals,"Unknown item (0x%02x)"));
921 item_len-=(asn->offset-*offset)+new_item_len;
922 *offset = asn->offset+new_item_len;
923 asn->offset = *offset;
924 /* do we have Event identifier ? */
927 itu = proto_tree_add_text(pres_tree_pp, tvb, *offset,item_len,
929 pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
931 (*offset)++; /* skip type */
932 asn->offset = *offset;
935 if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
938 *offset = asn->offset;
941 /* try to get Event identifier */
942 value = get_integer_value(asn,new_item_len,offset);
944 proto_tree_add_text(pres_tree_pc, tvb, *offset+1,new_item_len,
945 val_to_str(value, event_identifier_values_vals,"Unknown item (0x%02x)"));
946 item_len-=(asn->offset-*offset)+new_item_len;
947 *offset = asn->offset+new_item_len;
948 asn->offset = *offset;
952 show_user_data(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
953 *offset,int item_len,int tag)
955 proto_tree *pres_tree_ud = NULL;
956 proto_tree *pres_tree_pc = NULL;
959 guint start = asn->offset;
960 guint item_length = item_len;
962 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
963 item_len, "User data");
964 pres_tree_ud = proto_item_add_subtree(itm, ett_pres_ms);
965 itu = proto_tree_add_text(pres_tree_ud, tvb,
966 *offset,item_len+(asn->offset-*offset),
967 val_to_str(tag, user_data_values_vals,"Unknown item (0x%02x)"));
968 pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
971 case SIMPLY_ENCODED_DATA:
973 case FULLY_ENCODED_DATA:
974 show_fully_encoded_data(asn,pres_tree_pc,tvb,offset,item_len);
981 /* align the pointer */
982 (*offset)=start+item_length;
983 asn->offset = (*offset);
988 show_presentation_context_definition(ASN1_SCK *asn,proto_tree
989 *pres_tree,tvbuff_t *tvb,int *offset,int item_len,int tag)
991 proto_tree *pres_tree_ms = NULL;
992 proto_tree *pres_tree_pc = NULL;
999 guint start = asn->offset;
1000 guint item_length = item_len;
1002 itm = proto_tree_add_text(pres_tree, tvb,
1003 *offset,item_len+(asn->offset-*offset),
1004 val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
1005 pres_tree_pc = proto_item_add_subtree(itm, ett_pres_ms);
1007 /* do we have enough bytes to dissect ? */
1008 if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
1010 proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
1011 "Wrong item.Need %u bytes but have %u", item_len,length);
1012 /* align the pointer */
1013 (*offset)=start+item_length;
1014 asn->offset = (*offset);
1017 *offset =asn->offset;
1020 while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
1022 int old_offset = *offset;
1024 type = tvb_get_guint8(tvb, *offset);
1027 asn->offset = *offset;
1029 if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
1032 /* align the pointer */
1033 (*offset)=start+item_length;
1034 asn->offset = (*offset);
1037 header_len = asn->offset - (*offset) +1;
1038 /* do we have enough bytes to dissect ? */
1039 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
1042 proto_tree_add_text(pres_tree_pc, tvb, *offset, new_item_len,
1043 "Wrong item.Need %u bytes but have %u", new_item_len,length);
1044 /* align the pointer */
1045 (*offset)=start+item_length;
1046 asn->offset = (*offset);
1049 ms = proto_tree_add_text(pres_tree_pc, tvb, *offset-1,
1050 new_item_len+(asn->offset-*offset)+1,
1051 val_to_str(type, presentation_context_definition_vals,
1052 "Unknown item (0x%02x)"));
1053 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1054 *offset = asn->offset;
1061 if(tag == PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST
1062 || tag == DEFAULT_CONTEXT_RESULT)
1064 show_presentation_context_definition_result_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
1068 show_presentation_context_definition_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
1070 *offset = old_offset+(new_item_len+header_len);
1074 proto_tree_add_text(pres_tree_ms, tvb, *offset,
1075 new_item_len+(asn->offset-*offset),
1076 "Unknown asn.1 parameter: (0x%02x)", type);
1077 *offset = old_offset+(new_item_len+header_len);
1079 item_len = item_len - (new_item_len+header_len);
1084 /* align the pointer */
1085 (*offset)=start+item_length;
1086 asn->offset = (*offset);
1088 /* if we can't dissect */
1090 dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
1091 proto_tree *tree, const char *field_name, int ret)
1094 errstr = asn1_err_to_str(ret);
1098 proto_tree_add_text(tree, tvb, offset, 0,
1099 "ERROR: Couldn't parse %s: %s", field_name, errstr);
1100 call_dissector(data_handle,
1101 tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
1105 static int read_string_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
1106 proto_item **new_item, char **s, int start, guint length)
1109 proto_item *temp_item = NULL;
1114 ret = asn1_string_value_decode(a, length, &string);
1115 if (ret != ASN1_ERR_NOERROR)
1119 proto_tree_add_text(tree, a->tvb, start, 0,
1120 "%s: ERROR: Couldn't parse value: %s",
1121 proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
1125 string = g_realloc(string, length + 1);
1126 string[length] = '\0';
1132 temp_item = proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset
1135 *new_item = temp_item;
1142 return ASN1_ERR_NOERROR;
1145 show_provider_reason(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
1146 *offset,int item_len,int type)
1150 proto_tree *pres_tree_ms = NULL;
1151 proto_tree *pres_tree_pr = NULL;
1154 int new_item_len = item_len+(asn->offset-*offset);
1156 ms = proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
1157 val_to_str(type, sequence_top_vals,
1158 "Unknown item (0x%02x)"));
1159 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1160 value = get_integer_value(asn,item_len,offset);
1161 pr = proto_tree_add_text(pres_tree_ms, tvb, *offset, new_item_len,
1162 val_to_str(value, provider_reason_values_vals,
1163 "Unknown item (0x%02x)"));
1164 pres_tree_pr = proto_item_add_subtree(pr, ett_pres_ms);
1165 print_value(asn,pres_tree_pr,tvb,offset,item_len);
1166 asn->offset = *offset = off+new_item_len;
1169 show_presentation_selector (ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
1170 *tvb,int *offset,int item_len,int type)
1173 proto_tree *pres_tree_ms = NULL;
1177 ms = proto_tree_add_text(pres_tree, tvb, *offset,
1178 item_len+(asn->offset-*offset),
1179 val_to_str(type, sequence_top_vals,
1180 "Unknown item (0x%02x)"));
1183 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1185 ret = read_string_value(asn, pres_tree,0,NULL, &s,
1186 *offset+(asn->offset-*offset), item_len);
1187 if(ret == ASN1_ERR_NOERROR)
1189 proto_tree_add_text(pres_tree_ms, tvb, *offset+2, item_len,
1197 /* display top sequence */
1199 show_sequence_top(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
1200 *tvb,packet_info *pinfo,int *offset,int item_len)
1203 guint cls, con, tag,len1;
1208 while(item_len > 0 )
1210 /* do we have enough bytes to dissect this item ? */
1211 if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
1213 proto_tree_add_text(pres_tree, tvb, *offset, item_len,
1214 "Wrong Item.Need %u bytes but have %u", item_len,length);
1218 type = tvb_get_guint8(tvb, *offset);
1220 ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
1222 if (ret != ASN1_ERR_NOERROR)
1224 dissect_parse_error(tvb, *offset, pinfo, pres_tree,
1225 "sequence error", ret);
1228 item_len = item_len - (asn->offset - *offset);
1230 * [APPLICATION <tag>]
1235 /* Calling-presentation-selector and
1236 User data have the same tag number
1237 Try to recognize which one do we really have */
1238 if( con == ASN1_CON)
1240 /* it is User data */
1242 show_user_data(asn,pres_tree,tvb,offset,len1,type);
1245 /* it is Calling-presentation-selector */
1246 /* simply go below, we don't need to break here */
1248 case CALLED_PRESENTATION_SELECTOR:
1249 case RESPONDING_PRESENTATION_SELECTOR:
1250 /*case CALLING_PRESENTATION_SELECTOR:*/
1252 * [Called-presentation-selector]
1253 * [Calling-presentation-selector]
1254 * [Responding-presentation-selector]
1256 show_presentation_selector(asn,pres_tree,tvb,offset,len1,tag);
1258 case DEFAULT_CONTEXT_NAME:
1259 case PRESENTATION_CONTEXT_DEFINITION_LIST:
1260 show_presentation_context_definition(asn,pres_tree,tvb,offset,len1,tag);
1262 case PROTOCOL_VERSION:
1266 /* yes, it is application */
1267 *offset = asn->offset;
1271 show_protocol_version(asn,pres_tree,tvb,offset,len1,tag);
1273 case PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST:
1274 case DEFAULT_CONTEXT_RESULT:
1275 show_presentation_context_definition(asn,pres_tree,tvb,offset,len1,tag);
1277 case PRESENTATION_REQUIREMENTS:
1278 show_presentation_requirements(asn,pres_tree,tvb,offset,len1,tag);
1280 case PROVIDER_REASON:
1281 show_provider_reason(asn,pres_tree,tvb,offset,len1,tag);
1285 case USER_SESSION_REQUIREMENTS:
1287 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset
1289 val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
1290 (asn->offset)+=len1;
1294 itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset
1296 "Unknown tag: %x",tag);
1297 (asn->offset)+=len1;
1301 *offset = asn->offset;
1306 show_connection_request_confirm(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
1307 *tvb,packet_info *pinfo,int *offset,int* item_len)
1311 proto_tree *pres_tree_ms = NULL;
1313 /* get type of set */
1314 while ( tvb_reported_length_remaining(tvb, *offset) > 0 )
1318 type = tvb_get_guint8(tvb, *offset);
1319 asn1_tag = type & 0x1f;
1322 asn->offset = *offset;
1324 if (read_length(asn, pres_tree, 0, item_len) != ASN1_ERR_NOERROR)
1328 /* do we have enough bytes to dissect ? */
1329 if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
1332 proto_tree_add_text(pres_tree, tvb, *offset, -1,
1333 "Wrong item.Need %u bytes but have %u", *item_len,length);
1336 ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
1337 *item_len+(asn->offset-*offset)+1,
1338 val_to_str(asn1_tag, cr_vals,
1339 "Unknown item (0x%02x)"));
1340 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1345 proto_tree_add_uint(pres_tree_ms, hf_pres_ms_type, tvb, (*offset)-1, 1,
1347 proto_tree_add_text(pres_tree_ms, tvb, *offset, (asn->offset-*offset),
1348 "Lenght:%u",*item_len);
1349 *offset=asn->offset;
1350 show_integer(asn,pres_tree_ms,tvb,offset,*item_len);
1354 proto_tree_add_uint(pres_tree_ms, hf_pres_seq_type, tvb, (*offset)-1, 1,
1356 proto_tree_add_text(pres_tree_ms, tvb, *offset, (asn->offset-*offset),
1357 "Lenght:%u",*item_len);
1358 *offset=asn->offset;
1359 show_sequence_top(asn,pres_tree_ms,tvb,pinfo,offset,*item_len);
1362 proto_tree_add_text(pres_tree, tvb, (*offset)-1,
1363 *item_len+(asn->offset-*offset)+1,
1364 "Unknown asn.1 parameter: (0x%02x).Tag :(0x%02x)", type,asn1_tag);
1365 (*offset)+=*item_len+(asn->offset-*offset);
1366 asn->offset = *offset;
1377 dissect_ppdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
1381 proto_tree *pres_tree = NULL;
1387 /* do we have spdu type from the session dissector? */
1388 if( !pinfo->private_data )
1392 proto_tree_add_text(tree, tvb, offset, -1,
1393 "Internal error:can't get spdu type from session dissector.");
1399 session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
1400 if(session->spdu_type == 0 )
1404 proto_tree_add_text(tree, tvb, offset, -1,
1405 "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
1410 /* get type of tag */
1411 s_type = tvb_get_guint8(tvb, offset);
1412 /* set up type of Ppdu */
1413 if (check_col(pinfo->cinfo, COL_INFO))
1414 col_add_str(pinfo->cinfo, COL_INFO,
1415 val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
1418 ti = proto_tree_add_item(tree, proto_pres, tvb, offset, -1,
1420 pres_tree = proto_item_add_subtree(ti, ett_pres);
1423 /* open asn.1 stream */
1424 asn1_open(&asn, tvb, offset);
1426 switch(session->spdu_type)
1429 proto_tree_add_uint(pres_tree, hf_pres_type, tvb, offset-1, 1, s_type);
1430 if (read_length(&asn, pres_tree, hf_cp_type_message_length, &cp_type_len)
1431 != ASN1_ERR_NOERROR)
1436 offset = asn.offset;
1437 /* do we have enough bytes to dissect ? */
1438 if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
1443 proto_tree_add_text(pres_tree, tvb, offset, -1,
1444 "Wrong Ppdu.Need %u bytes but have %u", cp_type_len,length);
1450 asn.offset = offset;
1451 show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,cp_type_len);
1455 case SES_CONNECTION_REQUEST:
1456 case SES_CONNECTION_ACCEPT:
1457 proto_tree_add_uint(pres_tree, hf_pres_type, tvb, offset-1, 1, s_type);
1459 if (read_length(&asn, pres_tree, hf_cp_type_message_length, &cp_type_len)
1460 != ASN1_ERR_NOERROR)
1465 offset = asn.offset;
1466 /* do we have enough bytes to dissect ? */
1467 if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
1472 proto_tree_add_text(pres_tree, tvb, offset, -1,
1473 "Wrong Ppdu.Need %u bytes but have %u", cp_type_len,length);
1479 show_connection_request_confirm(&asn,pres_tree,tvb,pinfo,&offset,&cp_type_len);
1484 if (read_length(&asn, pres_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1489 offset = asn.offset;
1490 /* do we have enough bytes to dissect ? */
1491 if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
1495 proto_tree_add_text(pres_tree, tvb, offset, -1,
1496 "Wrong Ppdu.Need %u bytes but have %u", rest_len,length);
1500 if(session->abort_type == SESSION_USER_ABORT )
1503 if(s_type == ASN1_CLASS_PC+ASN1_CLASS_CONTEXT_SPECIFIC)
1508 show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,rest_len);
1517 show_session_provider_abort(&asn,pres_tree,tvb,&offset,rest_len);
1527 show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,rest_len);
1535 proto_tree *pres_tree_ms = NULL;
1536 /* back to length */
1539 if (read_length(&asn, pres_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
1543 ms = proto_tree_add_text(pres_tree, tvb, offset, rest_len,
1544 val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
1545 pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
1546 show_user_data(&asn,pres_tree_ms,tvb,&offset,rest_len,s_type);
1549 /* close asn.1 stream */
1550 asn1_close(&asn, &offset);
1556 * Dissect PPDUs inside a SPDU.
1559 dissect_pres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1562 /* first, try to check length */
1563 /* do we have at least 4 bytes */
1564 if (!tvb_bytes_exist(tvb, 0, 4))
1566 proto_tree_add_text(tree, tvb, offset, tvb_reported_length_remaining(tvb,
1569 return; /* no, it isn't a presentation PDU */
1572 /* we can't make any additional checking here */
1573 /* postpone it before dissector will have more information */
1575 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1576 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRES");
1577 if (check_col(pinfo->cinfo, COL_INFO))
1578 col_clear(pinfo->cinfo, COL_INFO);
1579 /* save pointers for calling the acse dissector */
1581 global_pinfo = pinfo;
1583 while (tvb_reported_length_remaining(tvb, offset) > 0)
1585 offset = dissect_ppdu(tvb, offset, pinfo, tree);
1586 if(offset == FALSE )
1588 proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
1589 offset = tvb_length(tvb);
1596 proto_register_pres(void)
1598 static hf_register_info hf[] =
1625 &hf_cp_type_message_length,
1628 "cp_type.message_length",
1633 "CP type Message Length",
1640 "Connection reqiest/confirm",
1646 "Connection reqiest/confirm",
1655 "pres.mode.selector",
1665 &hf_pres_protocol_version,
1668 "pres.protocol.version",
1706 &hf_protocol_version,
1708 "Protocol version 1",
1709 "pres.protocol.version",
1712 PRES_PROTOCOL_VERGION,
1713 "Protocol version 1",
1718 &hf_context_management,
1720 "Context management",
1721 "pres.context.management",
1724 PRES_CONTEXT_MANAGEMENT,
1725 "Context management",
1745 static gint *ett[] =
1753 module_t *pres_module;
1756 proto_pres = proto_register_protocol(PROTO_STRING_PRES, "PRES", "pres");
1757 proto_register_field_array(proto_pres, hf, array_length(hf));
1758 proto_register_subtree_array(ett, array_length(ett));
1760 pres_module = prefs_register_protocol(proto_pres, NULL);
1763 * Register the dissector by name, so other dissectors can
1764 * grab it by name rather than just referring to it directly
1765 * (you can't refer to it directly from a plugin dissector
1766 * on Windows without stuffing it into the Big Transfer Vector).
1768 register_dissector("pres", dissect_pres, proto_pres);
1772 proto_reg_handoff_pres(void)
1774 /* find data dissector */
1775 data_handle = find_dissector("data");
1776 /* define acse sub dissector */
1777 acse_handle = find_dissector("acse");