1 /*#define DEBUG_BER 1*/
2 /* TODO: change #.REGISTER signature to new_dissector_t and
3 * update call_ber_oid_callback() accordingly.
6 * Helpers for ASN.1/BER dissection
7 * Ronnie Sahlberg (C) 2004
11 * Ethereal - Network traffic analyzer
12 * By Gerald Combs <gerald@ethereal.com>
13 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 * ITU-T Recommendation X.690 (07/2002),
32 * Information technology ASN.1 encoding rules:
33 * Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
47 #include <epan/packet.h>
49 #include <epan/strutil.h>
50 #include <epan/prefs.h>
51 #include "packet-ber.h"
54 static gint proto_ber = -1;
55 static gint hf_ber_id_class = -1;
56 static gint hf_ber_id_pc = -1;
57 static gint hf_ber_id_uni_tag = -1;
58 static gint hf_ber_id_tag = -1;
59 static gint hf_ber_length = -1;
60 static gint hf_ber_bitstring_padding = -1;
61 static gint hf_ber_unknown_OID = -1;
62 static gint hf_ber_unknown_OCTETSTRING = -1;
63 static gint hf_ber_unknown_NumericString = -1;
64 static gint hf_ber_unknown_PrintableString = -1;
65 static gint hf_ber_unknown_IA5String = -1;
66 static gint hf_ber_unknown_INTEGER = -1;
67 static gint hf_ber_unknown_ENUMERATED = -1;
69 static gint ett_ber_octet_string = -1;
70 static gint ett_ber_unknown = -1;
71 static gint ett_ber_SEQUENCE = -1;
73 static gboolean show_internal_ber_fields = FALSE;
75 proto_item *ber_last_created_item=NULL;
77 static dissector_table_t ber_oid_dissector_table=NULL;
79 static const value_string ber_class_codes[] = {
80 { BER_CLASS_UNI, "Universal" },
81 { BER_CLASS_APP, "Application" },
82 { BER_CLASS_CON, "Context Specific" },
83 { BER_CLASS_PRI, "Private" },
87 static const true_false_string ber_pc_codes = {
88 "Constructed Encoding",
92 static const value_string ber_uni_tag_codes[] = {
93 { BER_UNI_TAG_EOC , "'end-of-content'" },
94 { BER_UNI_TAG_BOOLEAN , "BOOLEAN" },
95 { BER_UNI_TAG_INTEGER , "INTEGER" },
96 { BER_UNI_TAG_BITSTRING , "BIT STRING" },
97 { BER_UNI_TAG_OCTETSTRING , "OCTET STRING" },
98 { BER_UNI_TAG_NULL , "NULL" },
99 { BER_UNI_TAG_OID , "OBJECT IDENTIFIER" },
100 { BER_UNI_TAG_ObjectDescriptor, "ObjectDescriptor" },
101 { BER_UNI_TAG_REAL , "REAL" },
102 { BER_UNI_TAG_ENUMERATED , "ENUMERATED" },
103 { BER_UNI_TAG_EMBEDDED_PDV , "EMBEDDED PDV" },
104 { BER_UNI_TAG_UTF8String , "UTF8String" },
105 { BER_UNI_TAG_RELATIVE_OID , "RELATIVE-OID" },
106 { BER_UNI_TAG_SEQUENCE , "SEQUENCE, SEQUENCE OF" },
107 { BER_UNI_TAG_SET , "SET, SET OF" },
108 { BER_UNI_TAG_NumericString , "NumericString" },
109 { BER_UNI_TAG_PrintableString , "PrintableString" },
110 { BER_UNI_TAG_TeletexString , "TeletexString, T61String" },
111 { BER_UNI_TAG_VideotexString , "VideotexString" },
112 { BER_UNI_TAG_IA5String , "IA5String" },
113 { BER_UNI_TAG_UTCTime , "UTCTime" },
114 { BER_UNI_TAG_GeneralizedTime , "GeneralizedTime" },
115 { BER_UNI_TAG_GraphicString , "GraphicString" },
116 { BER_UNI_TAG_VisibleString , "VisibleString, ISO64String" },
117 { BER_UNI_TAG_GeneralString , "GeneralString" },
118 { BER_UNI_TAG_UniversalString , "UniversalString" },
119 { BER_UNI_TAG_CHARACTERSTRING , "CHARACTER STRING" },
120 { BER_UNI_TAG_BMPString , "BMPString" },
125 proto_item *get_ber_last_created_item(void) {
126 return ber_last_created_item;
130 static GHashTable *oid_table=NULL;
133 dissect_ber_oid_NULL_callback(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_)
139 register_ber_oid_dissector(char *oid, dissector_t dissector, int proto, char *name)
141 dissector_handle_t dissector_handle;
143 dissector_handle=create_dissector_handle(dissector, proto);
144 dissector_add_string("ber.oid", oid, dissector_handle);
145 g_hash_table_insert(oid_table, oid, name);
147 /* Register the oid name to get translation in proto dissection */
149 register_ber_oid_name(char *oid, char *name)
151 g_hash_table_insert(oid_table, oid, name);
154 /* Get oid name fom has table to get translation in proto dissection(packet-per.c) */
156 get_ber_oid_name(char *oid)
158 return g_hash_table_lookup(oid_table, oid);
162 /* this function tries to dissect an unknown blob as much as possible.
163 * everytime this function is called it is a failure to implement a proper
164 * dissector in ethereal.
165 * something is missing, so dont become too comfy with this one,
166 * when it is called it is a BAD thing not a good thing.
167 * It can not handle IMPLICIT tags nor indefinite length.
170 dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree)
177 proto_item *item=NULL;
178 proto_tree *next_tree=NULL;
182 offset=dissect_ber_identifier(pinfo, NULL, tvb, offset, &class, &pc, &tag);
183 offset=dissect_ber_length(pinfo, NULL, tvb, offset, &len, &ind);
185 if(len>(guint32)tvb_length_remaining(tvb, offset)){
186 /* hmm maybe something bad happened or the frame is short,
187 since these are not vital outputs just return instead of
188 throwing en exception.
190 proto_tree_add_text(tree, tvb, offset, len, "BER: Error length:%d longer than tvb_length_ramaining:%d",len, tvb_length_remaining(tvb, offset));
191 return tvb_length(tvb);
197 case BER_UNI_TAG_INTEGER:
198 offset = dissect_ber_integer(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_INTEGER, NULL);
200 case BER_UNI_TAG_ENUMERATED:
201 offset = dissect_ber_integer(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_ENUMERATED, NULL);
203 case BER_UNI_TAG_OCTETSTRING:
204 offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_OCTETSTRING, NULL);
206 case BER_UNI_TAG_OID:
207 offset=dissect_ber_object_identifier(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_OID, NULL);
209 case BER_UNI_TAG_SEQUENCE:
210 item=proto_tree_add_text(tree, tvb, start_offset, len, "SEQUENCE");
212 next_tree=proto_item_add_subtree(item, ett_ber_SEQUENCE);
214 offset=dissect_unknown_ber(pinfo, tvb, offset, next_tree);
216 case BER_UNI_TAG_NumericString:
217 offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_NumericString, NULL);
219 case BER_UNI_TAG_PrintableString:
220 offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_PrintableString, NULL);
222 case BER_UNI_TAG_IA5String:
223 offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start_offset, hf_ber_unknown_IA5String, NULL);
226 proto_tree_add_text(tree, tvb, offset, len, "BER: Error can not handle universal tag:%d",tag);
231 item=proto_tree_add_text(tree, tvb, start_offset, len, "[%d]",tag);
233 next_tree=proto_item_add_subtree(item, ett_ber_SEQUENCE);
235 offset=dissect_unknown_ber(pinfo, tvb, offset, next_tree);
238 proto_tree_add_text(tree, tvb, offset, len, "BER: Error can not handle class:%d (0x%02x)",class,tvb_get_guint8(tvb, start_offset));
239 /* some printout here? aborting dissection */
240 return tvb_length(tvb);
243 /* were there more data to eat? */
244 if(offset<(int)tvb_length(tvb)){
245 offset=dissect_unknown_ber(pinfo, tvb, offset, tree);
253 call_ber_oid_callback(char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
257 next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_length_remaining(tvb, offset));
258 if(!dissector_try_string(ber_oid_dissector_table, oid, next_tvb, pinfo, tree)){
259 proto_item *item=NULL;
260 proto_tree *next_tree=NULL;
262 item=proto_tree_add_text(tree, next_tvb, 0, tvb_length_remaining(tvb, offset), "BER: Dissector for OID:%s not implemented. Contact Ethereal developers if you want this supported", oid);
264 next_tree=proto_item_add_subtree(item, ett_ber_unknown);
266 dissect_unknown_ber(pinfo, next_tvb, offset, next_tree);
269 /*XXX until we change the #.REGISTER signature for _PDU()s
270 * into new_dissector_t we have to do this kludge with
271 * manually step past the content in the ANY type.
273 offset+=tvb_length_remaining(tvb, offset);
279 static int dissect_ber_sq_of(gboolean implicit_tag, gint32 type, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id);
281 /* 8.1 General rules for encoding */
283 /* 8.1.2 Identifier octets */
284 int get_ber_identifier(tvbuff_t *tvb, int offset, gint8 *class, gboolean *pc, gint32 *tag) {
290 id = tvb_get_guint8(tvb, offset);
294 tmp_class = (id>>6) & 0x03;
295 tmp_pc = (id>>5) & 0x01;
298 if (tmp_tag == 0x1F) {
300 while (tvb_length_remaining(tvb, offset) > 0) {
301 t = tvb_get_guint8(tvb, offset);
319 int dissect_ber_identifier(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gint8 *class, gboolean *pc, gint32 *tag)
321 int old_offset = offset;
326 offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
328 if(show_internal_ber_fields){
329 proto_tree_add_uint(tree, hf_ber_id_class, tvb, old_offset, 1, tmp_class<<6);
330 proto_tree_add_boolean(tree, hf_ber_id_pc, tvb, old_offset, 1, (tmp_pc)?0x20:0x00);
331 if(tmp_class==BER_CLASS_UNI){
332 proto_tree_add_uint(tree, hf_ber_id_uni_tag, tvb, old_offset, offset - old_offset, tmp_tag);
334 proto_tree_add_uint(tree, hf_ber_id_tag, tvb, old_offset, offset - old_offset, tmp_tag);
348 /* this function gets the length octets of the BER TLV.
349 * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
351 /* 8.1.3 Length octets */
353 get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind) {
361 oct = tvb_get_guint8(tvb, offset);
372 oct = tvb_get_guint8(tvb, offset);
374 tmp_length = (tmp_length<<8) + oct;
384 *length = tmp_length;
391 /* this function dissects the length octets of the BER TLV.
392 * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
395 dissect_ber_length(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind)
397 int old_offset = offset;
401 offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
403 if(show_internal_ber_fields){
405 proto_tree_add_text(tree, tvb, old_offset, 1, "Length: Indefinite length");
407 proto_tree_add_uint(tree, hf_ber_length, tvb, old_offset, offset - old_offset, tmp_length);
411 *length = tmp_length;
417 /* 8.7 Encoding of an octetstring value */
419 dissect_ber_octet_string(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb) {
430 header_field_info *hfinfo;
432 hfinfo = proto_registrar_get_nth(hf_id);
437 if(tvb_length_remaining(tvb,offset)>3){
438 printf("OCTET STRING dissect_ber_octet string(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n",name,implicit_tag,offset,tvb_length_remaining(tvb,offset),tvb_get_guint8(tvb,offset),tvb_get_guint8(tvb,offset+1),tvb_get_guint8(tvb,offset+2));
440 printf("OCTET STRING dissect_ber_octet_string(%s) entered\n",name);
446 /* read header and len for the octet string */
447 offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
448 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
449 end_offset=offset+len;
451 /* sanity check: we only handle Constructed Universal Sequences */
452 if( (class!=BER_CLASS_UNI)
453 ||((tag<BER_UNI_TAG_NumericString)&&(tag!=BER_UNI_TAG_OCTETSTRING)&&(tag!=BER_UNI_TAG_UTF8String)) ){
454 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: OctetString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
458 /* implicit tag so just trust the length of the tvb */
460 len=tvb_length_remaining(tvb,offset);
461 end_offset=offset+len;
464 ber_last_created_item = NULL;
471 it = proto_tree_add_item(tree, hf_id, tvb, offset, len, FALSE);
472 ber_last_created_item = it;
475 if(len<=(guint32)tvb_length_remaining(tvb, offset)){
476 *out_tvb = tvb_new_subset(tvb, offset, len, len);
478 *out_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_length_remaining(tvb, offset));
485 int dissect_ber_octet_string_wcb(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_callback func)
489 offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_id, (func)?&out_tvb:NULL);
490 if (func && (tvb_length(out_tvb)>0)) {
492 tree = proto_item_add_subtree(ber_last_created_item, ett_ber_octet_string);
493 func(pinfo, tree, out_tvb, 0);
500 dissect_ber_integer(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value)
513 header_field_info *hfinfo;
515 hfinfo = proto_registrar_get_nth(hf_id);
520 if(tvb_length_remaining(tvb,offset)>3){
521 printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n",name,implicit_tag,offset,tvb_length_remaining(tvb,offset),tvb_get_guint8(tvb,offset),tvb_get_guint8(tvb,offset+1),tvb_get_guint8(tvb,offset+2));
523 printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d len:%d\n",name,implicit_tag,len);
530 offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
531 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
533 len=tvb_length_remaining(tvb, offset);
536 /* ok, we cant handle >4 byte integers so lets fake them */
538 header_field_info *hfinfo;
541 hfinfo = proto_registrar_get_nth(hf_id);
542 pi=proto_tree_add_text(tree, tvb, offset, len, "%s : 0x", hfinfo->name);
545 proto_item_append_text(pi,"%02x",tvb_get_guint8(tvb, offset));
552 header_field_info *hfinfo;
556 /* extend sign bit */
557 val64 = (gint8)tvb_get_guint8(tvb, offset);
561 val64=(val64<<8)|tvb_get_guint8(tvb, offset);
564 hfinfo = proto_registrar_get_nth(hf_id);
565 proto_tree_add_text(tree, tvb, offset-len, len, "%s: %" PRIu64, hfinfo->name, val64);
571 /* extend sign bit */
572 val = (gint8)tvb_get_guint8(tvb, offset);
576 val=(val<<8)|tvb_get_guint8(tvb, offset);
580 ber_last_created_item=NULL;
583 /* XXX - what if "len" is not 1, 2, 3, or 4? */
584 ber_last_created_item=proto_tree_add_item(tree, hf_id, tvb, offset-len, len, FALSE);
595 dissect_ber_boolean(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
602 header_field_info *hfi;
604 offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
605 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
607 /* if(class!=BER_CLASS_UNI)*/
609 val=tvb_get_guint8(tvb, offset);
612 ber_last_created_item=NULL;
615 hfi = proto_registrar_get_nth(hf_id);
616 if (hfi->type == FT_BOOLEAN)
617 ber_last_created_item=proto_tree_add_boolean(tree, hf_id, tvb, offset-1, 1, val);
619 ber_last_created_item=proto_tree_add_uint(tree, hf_id, tvb, offset-1, 1, val?1:0);
629 /* this function dissects a BER sequence
631 int dissect_ber_sequence(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
633 gboolean pc, ind, ind_field;
636 proto_tree *tree = parent_tree;
637 proto_item *item = NULL;
644 header_field_info *hfinfo;
646 hfinfo = proto_registrar_get_nth(hf_id);
651 if(tvb_length_remaining(tvb,offset)>3){
652 printf("SEQUENCE dissect_ber_sequence(%s) entered offset:%d len:%d %02x:%02x:%02x\n",name,offset,tvb_length_remaining(tvb,offset),tvb_get_guint8(tvb,offset),tvb_get_guint8(tvb,offset+1),tvb_get_guint8(tvb,offset+2));
654 printf("SEQUENCE dissect_ber_sequence(%s) entered\n",name);
659 /* first we must read the sequence header */
660 offset = dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
661 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
663 /* if the length is indefinite we dont really know (yet) where the
664 * object ends so assume it spans the rest of the tvb for now.
666 end_offset = tvb_length(tvb);
668 end_offset = offset + len;
671 /* sanity check: we only handle Constructed Universal Sequences */
673 ||(!implicit_tag&&((class!=BER_CLASS_UNI)
674 ||(tag!=BER_UNI_TAG_SEQUENCE)))) {
675 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Sequence expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
679 /* was implicit tag so just use the length of the tvb */
680 len=tvb_length_remaining(tvb,offset);
681 end_offset=offset+len;
687 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
688 tree = proto_item_add_subtree(item, ett_id);
692 /* loop over all entries until we reach the end of the sequence */
693 while (offset < end_offset){
698 int hoffset, eoffset, count;
700 if(ind){ /* this sequence was of indefinite length, so check for EOC */
701 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
702 if(show_internal_ber_fields){
703 proto_tree_add_text(tree, tvb, offset, 2, "EOC");
709 /* read header and len for next field */
710 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
711 offset = get_ber_length(tvb, offset, &len, &ind_field);
712 eoffset = offset + len;
713 ber_sequence_try_again:
714 /* have we run out of known entries in the sequence ?*/
716 /* it was not, move to the enxt one and try again */
717 proto_tree_add_text(tree, tvb, offset, len, "BER Error: This field lies beyond the end of the known sequence definition.");
722 /* Verify that this one is the one we want.
723 * Skip check completely if class==ANY
724 * of if NOCHKTAG is set
726 /* XXX Bug in asn2eth,
727 * for scope [7] Scope OPTIONAL,
729 * { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_scope },
730 * and there should not be a NOTCHKTAG here
732 if( (seq->class==BER_CLASS_CON) && (!(seq->flags&BER_FLAGS_NOOWNTAG)) ){
733 if( (seq->class!=BER_CLASS_ANY)
735 &&( (seq->class!=class)
736 ||(seq->tag!=tag) ) ){
737 /* it was not, move to the enxt one and try again */
738 if(seq->flags&BER_FLAGS_OPTIONAL){
739 /* well this one was optional so just skip to the next one and try again. */
741 goto ber_sequence_try_again;
744 proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in SEQUENCE expected class:%d tag:%d but found class:%d tag:%d",seq->class,seq->tag,class,tag);
749 } else if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
750 if( (seq->class!=BER_CLASS_ANY)
752 &&( (seq->class!=class)
753 ||(seq->tag!=tag) ) ){
754 /* it was not, move to the enxt one and try again */
755 if(seq->flags&BER_FLAGS_OPTIONAL){
756 /* well this one was optional so just skip to the next one and try again. */
758 goto ber_sequence_try_again;
761 proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in sequence expected class:%d tag:%d but found class:%d tag:%d",seq->class,seq->tag,class,tag);
768 if (!(seq->flags & BER_FLAGS_NOOWNTAG) ) {
769 /* dissect header and len for field */
770 hoffset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
771 hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
774 /* call the dissector for this field */
776 || ((eoffset-hoffset)>tvb_length_remaining(tvb, hoffset)) ){
777 /* If the field is indefinite (i.e. we dont know the
778 * length) of if the tvb is short, then just
779 * give it all of the tvb and hope for the best.
781 next_tvb = tvb_new_subset(tvb, hoffset, tvb_length_remaining(tvb,hoffset), tvb_length_remaining(tvb,hoffset));
783 next_tvb = tvb_new_subset(tvb, hoffset, eoffset-hoffset, eoffset-hoffset);
789 header_field_info *hfinfo;
791 hfinfo = proto_registrar_get_nth(hf_id);
796 if(tvb_length_remaining(next_tvb,0)>3){
797 printf("SEQUENCE dissect_ber_sequence(%s) calling subdissector offset:%d len:%d %02x:%02x:%02x\n",name,offset,tvb_length_remaining(next_tvb,0),tvb_get_guint8(next_tvb,0),tvb_get_guint8(next_tvb,1),tvb_get_guint8(next_tvb,2));
799 printf("SEQUENCE dissect_ber_sequence(%s) calling subdissector\n",name);
803 count=seq->func(pinfo, tree, next_tvb, 0);
807 header_field_info *hfinfo;
809 hfinfo = proto_registrar_get_nth(hf_id);
814 printf("SEQUENCE dissect_ber_sequence(%s) subdissector ate %d bytes\n",name,count);
818 offset = hoffset+count;
819 /* if it was optional and no bytes were eaten,
822 if((count==0)&&(seq->flags&BER_FLAGS_OPTIONAL)){
823 goto ber_sequence_try_again;
827 /* if we didnt end up at exactly offset, then we ate too many bytes */
828 if (offset != end_offset) {
829 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Sequence ate %d too many bytes", offset-end_offset);
837 /* this function dissects a BER choice
838 * If we did not find a matching choice, just return offset unchanged
839 * in case it was a CHOICE { } OPTIONAL
842 dissect_ber_choice(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_choice_t *choice, gint hf_id, gint ett_id)
848 const ber_choice_t *ch;
849 proto_tree *tree=parent_tree;
850 proto_item *item=NULL;
851 int end_offset, start_offset, count;
852 int hoffset = offset;
853 header_field_info *hfinfo;
854 gint reported_length, length;
860 header_field_info *hfinfo;
862 hfinfo = proto_registrar_get_nth(hf_id);
867 if(tvb_length_remaining(tvb,offset)>3){
868 printf("CHOICE dissect_ber_choice(%s) entered offset:%d len:%d %02x:%02x:%02x\n",name,offset,tvb_length_remaining(tvb,offset),tvb_get_guint8(tvb,offset),tvb_get_guint8(tvb,offset+1),tvb_get_guint8(tvb,offset+2));
870 printf("CHOICE dissect_ber_choice(%s) entered len:%d\n",name,tvb_length_remaining(tvb,offset));
876 /* read header and len for choice field */
877 offset=get_ber_identifier(tvb, offset, &class, &pc, &tag);
878 offset=get_ber_length(tvb, offset, &len, &ind);
880 /* if the length is indefinite we dont really know (yet) where the
881 * object ends so assume it spans the rest of the tvb for now.
882 * XXX - what if it runs past the end of the tvb because we
883 * need to do reassembly?
885 end_offset = tvb_length(tvb);
887 end_offset = offset + len;
890 /* Some sanity checks.
891 * The hf field passed to us MUST be an integer type
894 hfinfo=proto_registrar_get_nth(hf_id);
895 switch(hfinfo->type) {
902 proto_tree_add_text(tree, tvb, offset, len,"dissect_ber_choice(): Was passed a HF field that was not integer type : %s",hfinfo->abbrev);
903 fprintf(stderr,"dissect_ber_choice(): frame:%d offset:%d Was passed a HF field that was not integer type : %s\n",pinfo->fd->num,offset,hfinfo->abbrev);
910 /* loop over all entries until we find the right choice or
911 run out of entries */
916 printf("CHOICE testing potential subdissector class:%d:(expected)%d tag:%d:(expected)%d flags:%d\n",class,ch->class,tag,ch->tag,ch->flags);
918 if( ((ch->class==class)&&(ch->tag==tag))
919 || ((ch->class==class)&&(ch->tag==-1)&&(ch->flags&BER_FLAGS_NOOWNTAG))
921 if (!(ch->flags & BER_FLAGS_NOOWNTAG)){
922 /* dissect header and len for field */
923 hoffset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, NULL, NULL, NULL);
924 hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
925 start_offset=hoffset;
930 item = proto_tree_add_uint(parent_tree, hf_id, tvb, hoffset, end_offset - hoffset, ch->value);
931 tree = proto_item_add_subtree(item, ett_id);
935 reported_length = end_offset-start_offset;
936 length = tvb_length_remaining(tvb, hoffset);
937 if (length > reported_length)
938 length = reported_length;
939 next_tvb=tvb_new_subset(tvb, hoffset, length, reported_length);
944 header_field_info *hfinfo;
946 hfinfo = proto_registrar_get_nth(hf_id);
951 if(tvb_length_remaining(next_tvb,0)>3){
952 printf("CHOICE dissect_ber_choice(%s) calling subdissector start_offset:%d offset:%d len:%d %02x:%02x:%02x\n",name,start_offset,offset,tvb_length_remaining(next_tvb,0),tvb_get_guint8(next_tvb,0),tvb_get_guint8(next_tvb,1),tvb_get_guint8(next_tvb,2));
954 printf("CHOICE dissect_ber_choice(%s) calling subdissector len:%d\n",name,tvb_length(next_tvb));
958 count=ch->func(pinfo, tree, next_tvb, 0);
962 header_field_info *hfinfo;
964 hfinfo = proto_registrar_get_nth(hf_id);
969 printf("CHOICE dissect_ber_choice(%s) subdissector ate %d bytes\n",name,count);
972 if((count==0)&&(ch->class==class)&&(ch->tag==-1)&&(ch->flags&BER_FLAGS_NOOWNTAG)){
973 /* wrong one, break and try again */
975 goto choice_try_again;
978 offset=hoffset+count;
980 /* this choice was of indefinite length so we
981 * just have to trust what the subdissector
982 * told us about the length consumed.
993 /*XXX here we should have another flag to the CHOICE to distinguish
994 * between teh case when we know it is a mandatory or if the CHOICE is optional == no arm matched */
996 /* oops no more entries and we still havent found
999 proto_tree_add_text(tree, tvb, offset, len, "BER Error: This choice field was not found.");
1004 return start_offset;
1008 /* this function dissects a BER GeneralString
1011 dissect_ber_GeneralString(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, int name_len)
1029 /* first we must read the GeneralString header */
1030 offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
1031 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
1032 end_offset=offset+len;
1034 /* sanity check: we only handle Universal GeneralString*/
1035 if( (class!=BER_CLASS_UNI)
1036 ||(tag!=BER_UNI_TAG_GENSTR) ){
1037 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: GeneralString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
1041 if(len>=(max_len-1)){
1045 tvb_memcpy(tvb, str, offset, len);
1049 proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
1056 dissect_ber_restricted_string(gboolean implicit_tag, gint32 type, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb) {
1062 int hoffset = offset;
1067 header_field_info *hfinfo;
1069 hfinfo = proto_registrar_get_nth(hf_id);
1074 if(tvb_length_remaining(tvb,offset)>3){
1075 printf("RESTRICTED STRING dissect_ber_octet string(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n",name,implicit_tag,offset,tvb_length_remaining(tvb,offset),tvb_get_guint8(tvb,offset),tvb_get_guint8(tvb,offset+1),tvb_get_guint8(tvb,offset+2));
1077 printf("RESTRICTED STRING dissect_ber_octet_string(%s) entered\n",name);
1082 if (!implicit_tag) {
1083 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1084 offset = get_ber_length(tvb, offset, &len, NULL);
1085 eoffset = offset + len;
1088 if( (class!=BER_CLASS_UNI)
1090 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: String with tag=%d expected but Class:%d PC:%d Tag:%d was unexpected", type, class, pc, tag);
1096 return dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, hoffset, hf_id, out_tvb);
1100 dissect_ber_GeneralString(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, guint name_len)
1104 offset = dissect_ber_restricted_string(FALSE, BER_UNI_TAG_GeneralString, pinfo, tree, tvb, offset, hf_id, (name_string)?&out_tvb:NULL);
1107 if (tvb_length(out_tvb) >= name_len) {
1108 tvb_memcpy(out_tvb, name_string, 0, name_len-1);
1109 name_string[name_len-1] = '\0';
1111 tvb_memcpy(out_tvb, name_string, 0, -1);
1112 name_string[tvb_length(out_tvb)] = '\0';
1119 /* 8.19 Encoding of an object identifier value */
1120 int dissect_ber_object_identifier(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *value_string) {
1128 char str[256],*strp, *name;
1134 header_field_info *hfinfo;
1136 hfinfo = proto_registrar_get_nth(hf_id);
1141 if(tvb_length_remaining(tvb,offset)>3){
1142 printf("OBJECT IDENTIFIER dissect_ber_object_identifier(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n",name,implicit_tag,offset,tvb_length_remaining(tvb,offset),tvb_get_guint8(tvb,offset),tvb_get_guint8(tvb,offset+1),tvb_get_guint8(tvb,offset+2));
1144 printf("OBJECT IDENTIFIER dissect_ber_object_identifier(%s) entered\n",name);
1150 value_string[0] = '\0';
1153 if (!implicit_tag) {
1155 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1156 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
1157 eoffset = offset + len;
1158 if( (class!=BER_CLASS_UNI)
1159 ||(tag != BER_UNI_TAG_OID) ){
1160 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Object Identifier expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
1164 len=tvb_length_remaining(tvb,offset);
1169 for (i=0,strp=str; i<len; i++){
1170 byte = tvb_get_guint8(tvb, offset);
1174 proto_tree_add_text(tree, tvb, offset, eoffset - offset, "BER Error: too long Object Identifier");
1180 strp += sprintf(strp, "%d.%d", byte/40, byte%40);
1184 value = (value << 7) | (byte & 0x7F);
1189 strp += sprintf(strp, ".%d", value);
1195 item=proto_tree_add_string(tree, hf_id, tvb, offset - len, len, str);
1196 /* see if we know the name of this oid */
1198 name=g_hash_table_lookup(oid_table, str);
1200 proto_item_append_text(item, " (%s)", name);
1206 strcpy(value_string, str);
1212 static int dissect_ber_sq_of(gboolean implicit_tag, gint32 type, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
1214 gboolean pc, ind, ind_field;
1217 proto_tree *tree = parent_tree;
1218 proto_item *item = NULL;
1219 int cnt, hoffset, end_offset;
1220 header_field_info *hfi;
1225 header_field_info *hfinfo;
1227 hfinfo = proto_registrar_get_nth(hf_id);
1232 if(tvb_length_remaining(tvb,offset)>3){
1233 printf("SQ OF dissect_ber_sq_of(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n",name,implicit_tag,offset,tvb_length_remaining(tvb,offset),tvb_get_guint8(tvb,offset),tvb_get_guint8(tvb,offset+1),tvb_get_guint8(tvb,offset+2));
1235 printf("SQ OF dissect_ber_sq_of(%s) entered\n",name);
1241 /* first we must read the sequence header */
1242 offset = dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
1243 offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
1245 /* if the length is indefinite we dont really know (yet) where the
1246 * object ends so assume it spans the rest of the tvb for now.
1248 end_offset = tvb_length(tvb);
1250 end_offset = offset + len;
1253 /* sanity check: we only handle Constructed Universal Sequences */
1255 ||(!implicit_tag&&((class!=BER_CLASS_UNI)
1257 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: %s Of expected but Class:%d PC:%d Tag:%d was unexpected",
1258 (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", class, pc, tag);
1262 len=tvb_length_remaining(tvb,offset);
1263 end_offset = offset + len;
1266 /* count number of items */
1269 while (offset < end_offset){
1272 if(ind){ /* this sequence of was of indefinite length, so check for EOC */
1273 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
1278 /* read header and len for next field */
1279 offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
1280 offset = get_ber_length(tvb, offset, &len, NULL);
1286 /* create subtree */
1288 hfi = proto_registrar_get_nth(hf_id);
1290 if (hfi->type == FT_NONE) {
1291 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
1292 proto_item_append_text(item, ":");
1294 item = proto_tree_add_uint(parent_tree, hf_id, tvb, offset, len, cnt);
1295 proto_item_append_text(item, (cnt==1)?" item":" items");
1297 tree = proto_item_add_subtree(item, ett_id);
1301 /* loop over all entries until we reach the end of the sequence */
1302 while (offset < end_offset){
1310 if(ind){ /* this sequence of was of indefinite length, so check for EOC */
1311 if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0)){
1312 if(show_internal_ber_fields){
1313 proto_tree_add_text(tree, tvb, offset, 2, "EOC");
1319 /* read header and len for next field */
1320 offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
1321 offset = get_ber_length(tvb, offset, &len, &ind_field);
1323 /* if the length is indefinite we dont really know (yet) where the
1324 * object ends so assume it spans the rest of the tvb for now.
1326 eoffset = tvb_length(tvb);
1328 eoffset = offset + len;
1331 /* verify that this one is the one we want */
1332 if(seq->class!=BER_CLASS_ANY){
1333 if ((seq->class!=class)
1334 ||(seq->tag!=tag) ){
1335 if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
1336 proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field in SQ OF");
1343 if (!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
1344 /* dissect header and len for field */
1345 hoffset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
1346 hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
1349 /* call the dissector for this field */
1350 count=seq->func(pinfo, tree, tvb, hoffset)-hoffset;
1352 /* previous field was of indefinite length so we have
1353 * no choice but use whatever the subdissector told us
1354 * as size for the field.
1357 offset = hoffset+count;
1364 /* if we didnt end up at exactly offset, then we ate too many bytes */
1365 if (offset != end_offset) {
1366 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: %s Of ate %d too many bytes",
1367 (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", offset-end_offset);
1373 int dissect_ber_sequence_of(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
1374 return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SEQUENCE, pinfo, parent_tree, tvb, offset, seq, hf_id, ett_id);
1377 int dissect_ber_set_of(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_sequence_t *seq, gint hf_id, gint ett_id) {
1378 return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SET, pinfo, parent_tree, tvb, offset, seq, hf_id, ett_id);
1382 dissect_ber_GeneralizedTime(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
1385 const guint8 *tmpstr;
1393 offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
1394 offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
1395 end_offset=offset+len;
1397 /* sanity check. we only handle universal/generalized time */
1398 if( (class!=BER_CLASS_UNI)
1399 ||(tag!=BER_UNI_TAG_GeneralizedTime)){
1400 proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: GeneralizedTime expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
1402 end_offset=offset+len;
1405 len=tvb_length_remaining(tvb,offset);
1406 end_offset=offset+len;
1410 tmpstr=tvb_get_ptr(tvb, offset, len);
1411 snprintf(str, 31, "%.4s-%.2s-%.2s %.2s:%.2s:%.2s (%.1s)",
1412 tmpstr, tmpstr+4, tmpstr+6, tmpstr+8,
1413 tmpstr+10, tmpstr+12, tmpstr+14);
1414 str[31]=0; /* just in case ... */
1417 proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
1424 /* 8.6 Encoding of a bitstring value */
1425 int dissect_ber_bitstring(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const asn_namedbit *named_bits, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
1431 guint8 pad=0, b0, b1, val;
1433 proto_item *item = NULL;
1434 proto_tree *tree = NULL;
1435 const asn_namedbit *nb;
1440 /* read header and len for the octet string */
1441 offset = dissect_ber_identifier(pinfo, parent_tree, tvb, offset, &class, &pc, &tag);
1442 offset = dissect_ber_length(pinfo, parent_tree, tvb, offset, &len, &ind);
1443 end_offset = offset + len;
1445 /* sanity check: we only handle Universal BitSrings */
1446 if (!implicit_tag) {
1447 if( (class!=BER_CLASS_UNI)
1448 ||(tag!=BER_UNI_TAG_BITSTRING) ){
1449 proto_tree_add_text(parent_tree, tvb, offset-2, 2, "BER Error: BitString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
1455 len=tvb_length_remaining(tvb,offset);
1456 end_offset=offset+len;
1459 ber_last_created_item = NULL;
1467 pad = tvb_get_guint8(tvb, offset);
1468 proto_tree_add_item(parent_tree, hf_ber_bitstring_padding, tvb, offset, 1, FALSE);
1472 item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
1473 ber_last_created_item = item;
1475 tree = proto_item_add_subtree(item, ett_id);
1479 if(len<=(guint32)tvb_length_remaining(tvb, offset)){
1480 *out_tvb = tvb_new_subset(tvb, offset, len, len);
1482 *out_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_length_remaining(tvb, offset));
1492 if (nb->bit < (8*len-pad)) {
1493 val = tvb_get_guint8(tvb, offset + nb->bit/8);
1494 val &= 0x80 >> (nb->bit%8);
1495 b0 = (nb->gb0 == -1) ? nb->bit/8 :
1496 ((guint32)nb->gb0)/8;
1497 b1 = (nb->gb1 == -1) ? nb->bit/8 :
1498 ((guint32)nb->gb1)/8;
1499 proto_tree_add_item(tree, *(nb->p_id), tvb, offset + b0, b1 - b0 + 1, FALSE);
1500 } else { /* 8.6.2.4 */
1502 proto_tree_add_boolean(tree, *(nb->p_id), tvb, offset + len, 0, 0x00);
1505 if (item && nb->tstr)
1506 proto_item_append_text(item, "%s%s", sep, nb->tstr);
1508 if (item && nb->fstr)
1509 proto_item_append_text(item, "%s%s", sep, nb->fstr);
1516 proto_item_append_text(item, ")");
1522 int dissect_ber_bitstring32(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, int **bit_fields, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
1528 header_field_info *hfi;
1531 unsigned int i, tvb_len;
1533 offset = dissect_ber_bitstring(implicit_tag, pinfo, parent_tree, tvb, offset, NULL, hf_id, ett_id, &tmp_tvb);
1535 tree = proto_item_get_subtree(ber_last_created_item);
1536 if (bit_fields && tree) {
1537 /* tmp_tvb points to the actual bitstring (including any pad bits at the end.
1538 * note that this bitstring is not neccessarily always encoded as 4 bytes
1539 * so we have to read it byte by byte.
1542 tvb_len=tvb_length(tmp_tvb);
1546 val|=tvb_get_guint8(tmp_tvb,i);
1553 proto_tree_add_boolean(tree, **bf, tmp_tvb, 0, tvb_len, val);
1554 hfi = proto_registrar_get_nth(**bf);
1555 if (val & hfi->bitmask) {
1556 proto_item_append_text(ber_last_created_item, "%s%s", sep, hfi->name);
1563 proto_item_append_text(ber_last_created_item, ")");
1573 proto_register_ber(void)
1575 static hf_register_info hf[] = {
1576 { &hf_ber_id_class, {
1577 "Class", "ber.id.class", FT_UINT8, BASE_DEC,
1578 VALS(ber_class_codes), 0xc0, "Class of BER TLV Identifier", HFILL }},
1579 { &hf_ber_bitstring_padding, {
1580 "Padding", "ber.bitstring.padding", FT_UINT8, BASE_DEC,
1581 NULL, 0x0, "Number of unsused bits in the last octet of the bitstring", HFILL }},
1583 "P/C", "ber.id.pc", FT_BOOLEAN, 8,
1584 TFS(&ber_pc_codes), 0x20, "Primitive or Constructed BER encoding", HFILL }},
1585 { &hf_ber_id_uni_tag, {
1586 "Tag", "ber.id.uni_tag", FT_UINT8, BASE_DEC,
1587 VALS(ber_uni_tag_codes), 0x1f, "Universal tag type", HFILL }},
1589 "Tag", "ber.id.tag", FT_UINT32, BASE_DEC,
1590 NULL, 0, "Tag value for non-Universal classes", HFILL }},
1592 "Length", "ber.length", FT_UINT32, BASE_DEC,
1593 NULL, 0, "Length of contents", HFILL }},
1594 { &hf_ber_unknown_OCTETSTRING, {
1595 "OCTETSTRING", "ber.unknown.OCTETSTRING", FT_BYTES, BASE_HEX,
1596 NULL, 0, "This is an unknown OCTETSTRING", HFILL }},
1597 { &hf_ber_unknown_OID, {
1598 "OID", "ber.unknown.OID", FT_STRING, BASE_NONE,
1599 NULL, 0, "This is an unknown Object Identifier", HFILL }},
1600 { &hf_ber_unknown_NumericString, {
1601 "NumericString", "ber.unknown.NumericString", FT_STRING, BASE_NONE,
1602 NULL, 0, "This is an unknown NumericString", HFILL }},
1603 { &hf_ber_unknown_PrintableString, {
1604 "PrintableString", "ber.unknown.PrintableString", FT_STRING, BASE_NONE,
1605 NULL, 0, "This is an unknown PrintableString", HFILL }},
1606 { &hf_ber_unknown_IA5String, {
1607 "IA5String", "ber.unknown.IA5String", FT_STRING, BASE_NONE,
1608 NULL, 0, "This is an unknown IA5String", HFILL }},
1609 { &hf_ber_unknown_INTEGER, {
1610 "INTEGER", "ber.unknown.INTEGER", FT_UINT32, BASE_DEC,
1611 NULL, 0, "This is an unknown INTEGER", HFILL }},
1612 { &hf_ber_unknown_ENUMERATED, {
1613 "ENUMERATED", "ber.unknown.ENUMERATED", FT_UINT32, BASE_DEC,
1614 NULL, 0, "This is an unknown ENUMERATED", HFILL }},
1618 static gint *ett[] = {
1619 &ett_ber_octet_string,
1623 module_t *ber_module;
1625 proto_ber = proto_register_protocol("Basic Encoding Rules (ASN.1 X.690)", "BER", "ber");
1626 proto_register_field_array(proto_ber, hf, array_length(hf));
1627 proto_register_subtree_array(ett, array_length(ett));
1629 proto_set_cant_toggle(proto_ber);
1631 /* Register preferences */
1632 ber_module = prefs_register_protocol(proto_ber, NULL);
1633 prefs_register_bool_preference(ber_module, "show_internals",
1634 "Show internal BER encapsulation tokens",
1635 "Whether the dissector should also display internal"
1636 " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields);
1638 ber_oid_dissector_table = register_dissector_table("ber.oid", "BER OID Dissectors", FT_STRING, BASE_NONE);
1639 oid_table=g_hash_table_new(g_str_hash, g_str_equal);
1643 proto_reg_handoff_ber(void)