Align the --with-pcap help message with other help messages.
[obnox/wireshark/wip.git] / packet-per.c
1 /*
2 XXX all this offset>>3 and calculations of bytes in the tvb everytime
3 we put something in the tree is just silly.  should be replaced with some
4 proper helper routines 
5 */
6 /* packet-per.c
7  * Routines for dissection of ASN.1 Aligned PER
8  * 2003  Ronnie Sahlberg
9  *
10  * $Id: packet-per.c,v 1.10 2003/07/31 10:26:35 sahlberg Exp $
11  *
12  * Ethereal - Network traffic analyzer
13  * By Gerald Combs <gerald@ethereal.com>
14  * Copyright 1998 Gerald Combs
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <glib.h>
36 #include <epan/packet.h>
37
38 #include <stdio.h>
39 #include <string.h>
40
41 #include "prefs.h"
42 #include "packet-per.h"
43
44
45 static int proto_per = -1;
46 static int hf_per_GeneralString_length = -1;
47 static int hf_per_extension_bit = -1;
48 static int hf_per_extension_present_bit = -1;
49 static int hf_per_choice_extension = -1;
50 static int hf_per_num_sequence_extensions = -1;
51 static int hf_per_small_number_bit = -1;
52 static int hf_per_optional_field_bit = -1;
53 static int hf_per_sequence_of_length = -1;
54 static int hf_per_object_identifier_length = -1;
55 static int hf_per_open_type_length = -1;
56 static int hf_per_octet_string_length = -1;
57
58
59 static gint ett_per_sequence_of_item = -1;
60
61
62 /*
63 #define DEBUG_ENTRY(x) \
64 printf("#%d  %s   tvb:0x%08x\n",pinfo->fd->num,x,(int)tvb);
65 */
66 #define DEBUG_ENTRY(x) \
67         ;
68
69
70
71 /* whether the PER helpers should put the internal PER fields into the tree
72    or not.
73 */
74 static guint display_internal_per_fields = TRUE;
75
76
77
78 static const true_false_string tfs_extension_present_bit = {
79         "",
80         ""
81 };
82 static const true_false_string tfs_extension_bit = {
83         "Extension bit is set",
84         "Extension bit is clear"
85 };
86 static const true_false_string tfs_small_number_bit = {
87         "The number is small, 0-63",
88         "The number is large, >63"
89 };
90 static const true_false_string tfs_optional_field_bit = {
91         "",
92         ""
93 };
94
95
96
97
98 /* 10.9 */
99 /* this decodes and returns a length determinant according to 10.9 */
100 guint32
101 dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, guint32 *length)
102 {
103         guint8 byte;
104         guint32 len;
105
106         if(!length){
107                 length=&len;
108         }
109
110         /* byte aligned */
111         if(offset&0x07){
112                 offset=(offset&0xfffffff8)+8;
113         }
114         byte=tvb_get_guint8(tvb, offset>>3);
115         offset+=8;
116
117         if((byte&0x80)==0){
118                 *length=byte;
119                 if(hf_index!=-1){
120                         proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
121                 }
122                 return offset;
123         }
124         if((byte&0xc0)==0x80){
125                 *length=(byte&0x3f);
126                 *length=((*length)<<8)+tvb_get_guint8(tvb, offset>>3);
127                 offset+=8;
128                 if(hf_index!=-1){
129                         proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-2, 2, *length);
130                 }
131                 return offset;
132         }
133         NOT_DECODED_YET("10.9.3.8.1");
134         return offset;
135 }
136
137 /* 10.6   normally small non-negative whole number */
138 guint32
139 dissect_per_normally_small_nonnegative_whole_number(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 *length)
140 {
141         gboolean small_number;
142         guint32 len;
143
144 DEBUG_ENTRY("dissect_per_normally_small_nonnegative_whole_number");
145         if(!length){
146                 length=&len;
147         }
148
149         offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_per_small_number_bit, &small_number, NULL);
150         if(!small_number){
151                 int i;
152                 /* 10.6.1 */
153                 *length=0;
154                 for(i=0;i<6;i++){
155                         offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &small_number, NULL);
156                         *length<<=1;
157                         if(small_number){
158                                 *length|=1;
159                         }
160                 }
161                 if(hf_index!=-1){
162                         if((offset&0x07)<7){
163                                 proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
164                         } else {
165                                 proto_tree_add_uint(tree, hf_index, tvb, (offset>>3), 1, *length);
166                         }
167                 }
168                 return offset;
169         }
170
171         /* 10.6.2 */
172         offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_index, length);
173
174         return offset;
175 }
176
177
178         
179 /* this function reads a GeneralString */
180 /* currently based on pure guesswork since RFC2833 didnt tell me much
181    i guess that the PER encoding for this is a normally-small-whole-number
182    followed by a ascii string.
183
184    based on pure guesswork.  it looks ok in the only capture i have where 
185    there is a 1 byte general string encoded
186 */
187 guint32
188 dissect_per_GeneralString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index)
189 {
190         proto_tree *etr=NULL;
191         guint32 length;
192
193         if(display_internal_per_fields){
194                 etr=tree;
195         }
196
197         offset=dissect_per_length_determinant(tvb, offset, pinfo, etr, hf_per_GeneralString_length, &length);
198
199
200         proto_tree_add_item(tree, hf_index, tvb, offset>>3, length, FALSE);
201
202         offset+=length*8;
203         
204         return offset;
205 }
206
207 /* 19 this function dissects a sequence of */
208 static guint32
209 dissect_per_sequence_of_helper(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *), guint32 length)
210 {
211         guint32 i;
212
213 DEBUG_ENTRY("dissect_per_sequence_of_helper");
214         for(i=0;i<length;i++){
215                 guint32 lold_offset=offset;
216                 proto_item *litem;
217                 proto_tree *ltree;
218
219                 litem=proto_tree_add_text(tree, tvb, offset>>3, 0, "Item %d", i);
220                 ltree=proto_item_add_subtree(litem, ett_per_sequence_of_item);
221
222                 offset=(*func)(tvb, offset, pinfo, ltree);
223                 proto_item_set_len(litem, (offset>>3)!=(lold_offset>>3)?(offset>>3)-(lold_offset>>3):1);
224         }
225
226         return offset;
227 }
228 guint32
229 dissect_per_sequence_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *))
230 {
231         proto_item *item;
232         proto_tree *tree;
233         guint32 old_offset=offset;
234         guint32 length;
235
236 DEBUG_ENTRY("dissect_per_sequence_of");
237
238         item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
239         tree=proto_item_add_subtree(item, ett_index);
240
241         /* semi-constrained whole number for number of elements */
242         /* each element encoded as 10.9 */
243         offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_per_sequence_of_length, &length);
244
245
246         offset=dissect_per_sequence_of_helper(tvb, offset, pinfo, tree, func, length);
247
248
249         proto_item_set_len(item, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1);
250         return offset;
251 }
252
253
254 /* dissect a constrained IA5String that consists of the full ASCII set,
255    i.e. no FROM stuff limiting the alphabet 
256 */
257 guint32
258 dissect_per_IA5String(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
259 {
260         offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_index, min_len, max_len);
261
262         return offset;
263 }
264
265 /* XXX we dont do >64k length strings   yet */
266 guint32
267 dissect_per_restricted_character_string(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len, char *alphabet, int alphabet_length)
268 {
269         guint32 length;
270         gboolean byte_aligned;
271         static char str[1024];
272         guint char_pos;
273         int bits_per_char;
274         guint32 old_offset;
275         
276 DEBUG_ENTRY("dissect_per_restricted_character_string");
277         /* xx.x if the length is 0 bytes there will be no encoding */
278         if(max_len==0){
279                 return offset;
280         }
281
282
283         if(min_len==-1){
284                 min_len=0;
285         }
286
287
288         /* xx.x */
289         length=max_len;
290         if(min_len!=max_len){
291                 offset=dissect_per_constrained_integer(tvb, offset, pinfo, 
292                         tree, hf_per_octet_string_length, min_len, max_len, 
293                         &length, NULL, FALSE);
294         } 
295
296
297
298         /* xx.x if length is fixed or constrained to be less than or equal to 
299            two bytes, then it will not be byte aligned. */
300         byte_aligned=TRUE;
301         if((min_len==max_len)&&(max_len<=2)){
302                 byte_aligned=FALSE;
303         }
304         if(max_len<2){
305                 byte_aligned=FALSE;
306         }
307
308         if(byte_aligned){
309                 if(offset&0x07){
310                         offset=(offset&0xfffffff8)+8;
311                 }
312         }
313
314
315         if(length>=1024){
316                 NOT_DECODED_YET("restricted char string too long");
317                 length=1024;
318         }
319
320         /* 27.5.2 depending of the alphabet length, find how many bits
321            are used to encode each character */
322 /* unaligned PER 
323         if(alphabet_length<=2){
324                 bits_per_char=1;
325         } else if(alphabet_length<=4){
326                 bits_per_char=2;
327         } else if(alphabet_length<=8){
328                 bits_per_char=3;
329         } else if(alphabet_length<=16){
330                 bits_per_char=4;
331         } else if(alphabet_length<=32){
332                 bits_per_char=5;
333         } else if(alphabet_length<=64){
334                 bits_per_char=6;
335         } else if(alphabet_length<=128){
336                 bits_per_char=7;
337         } else {
338                 bits_per_char=8;
339         }
340 */
341         if(alphabet_length<=2){
342                 bits_per_char=1;
343         } else if(alphabet_length<=4){
344                 bits_per_char=2;
345         } else if(alphabet_length<=16){
346                 bits_per_char=4;
347         } else {
348                 bits_per_char=8;
349         }
350
351         old_offset=offset;
352         for(char_pos=0;char_pos<length;char_pos++){
353                 guchar val;
354                 int i;
355                 gboolean bit;
356
357                 val=0;
358                 for(i=0;i<bits_per_char;i++){
359                         offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
360                         val=(val<<1)|bit;
361                 }
362                 str[char_pos]=alphabet[val];
363         }
364         str[char_pos]=0;
365         proto_tree_add_string(tree, hf_index, tvb, (old_offset>>3), (offset>>3)-(old_offset>>3), str);
366
367         return offset;
368 }
369 guint32
370 dissect_per_NumericString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
371 {
372         offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_index, min_len, max_len, " 0123456789", 11);
373
374         return offset;
375 }
376 guint32
377 dissect_per_PrintableString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
378 {
379         offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_index, min_len, max_len, " '()+,-.*0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 74);
380         return offset;
381 }
382 guint32
383 dissect_per_BMPString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
384 {
385         guint32 length;
386         static char *str;
387
388         /* xx.x if the length is 0 bytes there will be no encoding */
389         if(max_len==0){
390                 return offset;
391         }
392
393
394         if(min_len==-1){
395                 min_len=0;
396         }
397
398
399         /* xx.x */
400         length=max_len;
401         if(min_len!=max_len){
402                 offset=dissect_per_constrained_integer(tvb, offset, pinfo, 
403                         tree, hf_per_octet_string_length, min_len, max_len, 
404                         &length, NULL, FALSE);
405         } 
406
407
408         /* align to byte boundary */
409         if(offset&0x07){
410                 offset=(offset&0xfffffff8)+8;
411         }
412
413         if(length>=1024){
414                 NOT_DECODED_YET("BMPString too long");
415                 length=1024;
416         }
417
418         str = tvb_fake_unicode(tvb, offset>>3, length, FALSE);
419
420         proto_tree_add_string(tree, hf_index, tvb, offset>>3, length*2, str);
421
422         offset+=(length<<3)*2;
423
424         return offset;
425 }
426
427
428 /* this function dissects a constrained sequence of */
429 guint32
430 dissect_per_constrained_sequence_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *), int min_len, int max_len)
431 {
432         proto_item *item;
433         proto_tree *tree;
434         guint32 old_offset=offset;
435         guint32 length;
436
437
438 DEBUG_ENTRY("dissect_per_constrained_sequence_of");
439         item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
440         tree=proto_item_add_subtree(item, ett_index);
441
442         /* 19.5 if min==max and min,max<64k ==> no length determinant */
443         if((min_len==max_len) && (min_len<65536)){
444                 length=min_len;
445                 goto call_sohelper;
446         }
447
448         /* 19.6 ub>=64k or unset */
449         if(max_len>=65536){
450                 guint32 old_offset=offset;
451                 /* semi-constrained whole number for number of elements */
452                 /* each element encoded as 10.9 */
453                 offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, -1, &length);
454                 length+=min_len;
455                 proto_tree_add_uint(tree, hf_per_sequence_of_length, tvb, old_offset>>3, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1, length);
456                 goto call_sohelper;
457         }
458
459         /* constrained whole number for number of elements */
460         offset=dissect_per_constrained_integer(tvb, offset, pinfo, 
461                 tree, hf_per_sequence_of_length, min_len, max_len, 
462                 &length, NULL, FALSE);
463
464
465         
466 call_sohelper:
467         offset=dissect_per_sequence_of_helper(tvb, offset, pinfo, tree, func, length);
468
469
470         proto_item_set_len(item, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1);
471         return offset;
472 }
473
474 /* this function dissects a constrained set of */
475 guint32
476 dissect_per_constrained_set_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *), int min_len, int max_len)
477 {
478         /* for basic-per  a set-of is encoded in the same way as a sequence-of */
479 DEBUG_ENTRY("dissect_per_constrained_set_of");
480         offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, parent_tree, hf_index, ett_index, func, min_len, max_len);
481         return offset;
482 }
483
484
485
486
487
488
489 /* this function dissects a set of */
490 guint32
491 dissect_per_set_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *))
492 {
493         /* for basic-per  a set-of is encoded in the same way as a sequence-of */
494 DEBUG_ENTRY("dissect_per_set_of");
495         offset=dissect_per_sequence_of(tvb, offset, pinfo, parent_tree, hf_index, ett_index, func);
496         return offset;
497 }
498
499
500
501
502 /* this function reads a OBJECT IDENTIFIER */
503 guint32
504 dissect_per_object_identifier(tvbuff_t *tvb, guint32 offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index)
505 {
506         int i,count;
507         char str[256],*strp;
508         guint8 byte;
509         guint32 value;
510         proto_tree *etr=NULL;
511
512 DEBUG_ENTRY("dissect_per_object_identifier");
513
514         if(display_internal_per_fields){
515                 etr=tree;
516         }
517
518         /* first byte is the count and it is byte aligned */
519         if(offset&0x07){
520                 offset=(offset&0xfffffff8)+8;
521         }
522         count=tvb_get_guint8(tvb, offset>>3);
523
524
525         proto_tree_add_uint(etr, hf_per_object_identifier_length, tvb, offset>>3, 1, count);
526         offset+=8;
527
528         value=0;
529         for(i=0,strp=str;i<count;i++){
530                 byte=tvb_get_guint8(tvb,offset>>3);
531                 offset+=8;
532
533                 if((strp-str)>200){
534 NOT_DECODED_YET("too long octet_string");
535                         /*XXX assert here */
536                         return offset;
537                 }
538
539                 if(i==0){
540                         /* the first byte contains the first two object identifier components */
541                         if(byte<40){
542                                 strp+=sprintf(strp,"0.%d",byte);
543                         } else if (byte<80){
544                                 strp+=sprintf(strp,"1.%d",byte-40);
545                         } else {
546                                 strp+=sprintf(strp,"2.%d",byte-80);
547                         }
548                         continue;
549                 }
550
551                 value=(value<<7)|(byte&0x7f);
552                 if(byte&0x80){
553                         continue;
554                 }
555
556                 strp+=sprintf(strp,".%d",value);
557                 value=0;
558         }
559         *strp=0;
560
561         proto_tree_add_string(tree, hf_index, tvb, (offset>>3)-count, count, str);
562
563         return offset;
564 }
565
566
567
568
569 /* this function reads a single bit */
570 guint32
571 dissect_per_boolean(tvbuff_t *tvb, guint32 offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, gboolean *bool, proto_item **item)
572 {
573         guint8 ch, mask;
574         gboolean value;
575         header_field_info *hfi;
576         proto_item *it;
577
578 DEBUG_ENTRY("dissect_per_boolean");
579
580         ch=tvb_get_guint8(tvb, offset>>3);
581         mask=1<<(7-(offset&0x07));
582         if(ch&mask){
583                 value=1;
584         } else {
585                 value=0;
586         }
587         if(hf_index!=-1){
588                 char str[256];
589                 hfi = proto_registrar_get_nth(hf_index);
590                 sprintf(str,"%s: %c%c%c%c %c%c%c%c %s",
591                         hfi->name,
592                         mask&0x80?'0'+value:'.', 
593                         mask&0x40?'0'+value:'.', 
594                         mask&0x20?'0'+value:'.', 
595                         mask&0x10?'0'+value:'.', 
596                         mask&0x08?'0'+value:'.', 
597                         mask&0x04?'0'+value:'.', 
598                         mask&0x02?'0'+value:'.', 
599                         mask&0x01?'0'+value:'.',
600                         value?"Bit is set":"Bit is clear"
601                 );
602                 it=proto_tree_add_boolean_format(tree, hf_index, tvb, offset>>3, 1, value, str);
603                 if(item){
604                         *item=it;
605                 }
606         }
607
608         if(bool){
609                 *bool=value;
610         }
611         return offset+1;
612 }
613
614
615
616
617 /* we currently only handle integers up to 32 bits in length. */
618 guint32
619 dissect_per_integer(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, gint32 *value, proto_item **item)
620 {
621         guint32 i, length;
622         gint32 val;
623         proto_item *it=NULL;
624
625         /* 12.2.6 b */
626         offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, -1, &length);
627         /* gassert here? */
628         if(length>4){
629 NOT_DECODED_YET("too long integer");
630                 length=4;
631         }
632
633         val=0;
634         for(i=0;i<length;i++){
635                 if(i==0){
636                         if(tvb_get_guint8(tvb, offset>>3)&0x80){
637                                 /* negative number */
638                                 val=0xffffffff;
639                         } else {
640                                 /* positive number */
641                                 val=0;
642                         }
643                 }
644                 val=(val<<8)|tvb_get_guint8(tvb,offset>>3);
645                 offset+=8;
646         }
647         it=proto_tree_add_int(tree, hf_index, tvb, (offset>>3)-(length+1), length+1, val);
648                 
649         if(item){
650                 *item=it;
651         }
652         if(value){
653                 *value=val;
654         }
655
656         return offset;
657 }
658
659
660 /* this function reads a constrained integer  with or without a
661    PER visible extension marker present
662
663    has_extension==TRUE  would map to asn constructs such as:
664                 rfc-number      INTEGER (1..32768, ...)
665    while has_extension==FALSE would map to:
666                 t35CountryCode  INTEGER (0..255)
667
668    it only handles integers that fit inside a 32 bit integer
669 10.5.1 info only
670 10.5.2 info only
671 10.5.3 range=ub-lb+1
672 10.5.4 empty range
673 10.5.5 info only
674         10.5.6 unaligned version
675 10.5.7 aligned version
676 10.5.7.1 decoding of 0-255 1-8 bits
677 10.5.7.2 decoding og 0-256 8 bits
678 10.5.7.3 decoding of 0-65535 16 bits
679         10.5.7.4
680 */
681 guint32
682 dissect_per_constrained_integer(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 min, guint32 max, guint32 *value, proto_item **item, gboolean has_extension)
683 {
684         proto_item *it=NULL;
685         guint32 range, val;
686         header_field_info *hfi;
687         int num_bits;
688         int pad;
689         guint32 tmp;
690
691 DEBUG_ENTRY("dissect_per_constrained_integer");
692         if(has_extension){
693                 gboolean extension_present;
694                 offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &extension_present, NULL);
695                 if(extension_present){
696                         offset=dissect_per_integer(tvb, offset, pinfo, tree,
697                                 hf_index,
698                                 NULL, NULL);
699                         return offset;
700                 }
701         }
702
703         hfi = proto_registrar_get_nth(hf_index);
704
705         /* 10.5.3 */
706         if((max-min)>65536){
707                 /* just set range really big so it will fall through
708                    to the bottom of the encoding */
709                 range=1000000;
710         } else {
711                 range=max-min+1;
712         }
713
714         num_bits=0;
715         pad=0;
716         val=0;
717         /* 10.5.4 */
718         if(range==1){
719                 it=proto_tree_add_uint_format(tree, hf_index, tvb, offset>>3, 0, min, "%s: %d", hfi->name, min);
720                 if(item){
721                         *item=it;
722                 }
723                 if(value){
724                         *value=val;
725                 }
726                 return offset;
727         }
728
729         /* 10.5.7 */
730         if(range<=255){
731                 /* 10.5.7.1 */
732                 char str[256];
733                 int i, bit, length;
734
735                 length=1;
736                 if(range<=2){
737                         num_bits=1;
738                 } else if(range<=4){
739                         num_bits=2;
740                 } else if(range<=8){
741                         num_bits=3;
742                 } else if(range<=16){
743                         num_bits=4;
744                 } else if(range<=32){
745                         num_bits=5;
746                 } else if(range<=64){
747                         num_bits=6;
748                 } else if(range<=128){
749                         num_bits=7;
750                 } else if(range<=256){
751                         num_bits=8;
752                 }
753                 /* prepare the string */
754                 sprintf(str, "%s: ", hfi->name);
755                 for(bit=0;bit<((int)(offset&0x07));bit++){
756                         if(bit&&(!(bit%4))){
757                                 strcat(str, " ");
758                         }
759                         strcat(str,".");
760                 }
761                 /* read the bits for the int */
762                 for(i=0;i<num_bits;i++){
763                         if(bit&&(!(bit%4))){
764                                 strcat(str, " ");
765                         }
766                         if(bit&&(!(bit%8))){
767                                 length+=1;
768                                 strcat(str, " ");
769                         }
770                         bit++;
771                         offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &tmp, NULL);
772                         val<<=1;
773                         if(tmp){
774                                 val|=tmp;
775                                 strcat(str, "1");
776                         } else {
777                                 strcat(str, "0");
778                         }
779                 }
780                 for(;bit%8;bit++){
781                         if(bit&&(!(bit%4))){
782                                 strcat(str, " ");
783                         }
784                         strcat(str,".");
785                 }
786                 val+=min;
787                 if(hfi->strings){
788                         it=proto_tree_add_uint_format(tree, hf_index, tvb, (offset-num_bits)>>3, length, val, "%s : %s (%d)", str, val_to_str(val, hfi->strings, "Unknown(%d)"),val);
789                 } else {
790                         it=proto_tree_add_uint(tree, hf_index, tvb, (offset-num_bits)>>3, length, val);
791                 }
792                 if(item){
793                         *item=it;
794                 }
795                 if(value){
796                         *value=val;
797                 }
798                 return offset;
799         } else if(range==256){
800                 /* 10.5.7.2 */
801                 num_bits=8;
802                 pad=7-(offset&0x07);
803
804                 /* in the aligned case, align to byte boundary */
805                 if(offset&0x07){
806                         offset=(offset&0xfffffff8)+8;
807                 }
808                 val=tvb_get_guint8(tvb, offset>>3);
809                 offset+=8;
810
811                 val+=min;
812                 it=proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, val);
813                 if(item){
814                         *item=it;
815                 }
816                 if(value){
817                         *value=val;
818                 }
819                 return offset;
820         } else if(range<=65536){
821                 /* 10.5.7.3 */
822                 num_bits=16;
823                 pad=7-(offset&0x07);
824
825                 /* in the aligned case, align to byte boundary */
826                 if(offset&0x07){
827                         offset=(offset&0xfffffff8)+8;
828                 }
829                 val=tvb_get_guint8(tvb, offset>>3);
830                 val<<=8;
831                 offset+=8;
832                 val|=tvb_get_guint8(tvb, offset>>3);
833                 offset+=8;
834
835                 val+=min;
836                 it=proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-2, 2, val);
837                 if(item){
838                         *item=it;
839                 }
840                 if(value){
841                         *value=val;
842                 }
843                 return offset;
844         } else {
845                 int i,num_bytes;
846                 gboolean bit;
847                 
848                 /* 10.5.7.4 */
849                 /* 12.2.6 */
850                 offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
851                 num_bytes=bit;
852                 offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
853                 num_bytes=(num_bytes<<1)|bit;
854                 
855                 num_bytes++;  /* lower bound for length determinant is 1 */
856
857                 /* byte aligned */
858                 if(offset&0x07){
859                         offset=(offset&0xfffffff8)+8;
860                 }
861                 val=0;
862                 for(i=0;i<num_bytes;i++){
863                         val=(val<<8)|tvb_get_guint8(tvb,offset>>3);
864                         offset+=8;
865                 }
866                 val+=min;
867                 it=proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-(num_bytes+1), num_bytes+1, val);
868                 if(item){
869                         *item=it;
870                 }
871                 if(value){
872                         *value=val;
873                 }
874                 return offset;
875         }
876
877         NOT_DECODED_YET("10.5");
878         return offset;
879 }
880
881 /* this functions decodes a CHOICE
882    it can only handle CHOICE INDEX values that fits inside a 32 bit integer.
883            22.1
884            22.2
885            22.3
886            22.4
887            22.5
888 22.6 no extensions
889 22.7 extension marker == 0
890            22.8 extension marker == 1
891 */
892 guint32
893 dissect_per_choice(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, gint ett_index, per_choice_t *choice, char *name, guint32 *value)
894 {
895         gboolean extension_present, extension_flag;
896         int extension_root_entries;
897         guint32 choice_index;
898         int i;
899         proto_item *it=NULL;
900         proto_tree *tr=NULL;
901         guint32 old_offset=offset;
902
903 DEBUG_ENTRY("dissect_per_choice");
904
905         it=proto_tree_add_text(tree, tvb, offset>>3, 0, name);
906         tr=proto_item_add_subtree(it, ett_index);
907
908         
909         /* first check if there should be an extension bit for this CHOICE.
910            we do this by just checking the first choice arm 
911          */
912         if(choice[0].extension==NO_EXTENSIONS){
913                 extension_present=0;
914         } else {
915                 extension_present=1;
916                 /* will be placed called again below to place it in the tree */
917                 offset=dissect_per_boolean(tvb, offset, pinfo, tr, hf_per_extension_bit, &extension_flag, NULL);
918         }
919
920         /* count the number of entries in the extension_root */
921         extension_root_entries=0;
922         for(i=0;choice[i].name;i++){
923                 switch(choice[i].extension){
924                 case NO_EXTENSIONS:
925                 case EXTENSION_ROOT:
926                         extension_root_entries++;
927                         break;
928                 }
929         }
930
931         if( (!extension_present)
932         ||  (extension_present && (extension_flag==0)) ){
933                 guint32 choice_offset=offset;
934                 proto_tree *choicetree;
935                 proto_item *choiceitem;
936                 proto_tree *etr=NULL;
937
938                 /* 22.6 */
939                 /* 22.7 */
940 /*qqq  make it similar to the section below instead */
941                 offset=dissect_per_constrained_integer(tvb, offset, pinfo, 
942                         tr, hf_index, 0, extension_root_entries-1, 
943                         &choice_index, &choiceitem, FALSE);
944                 if(value){
945                         *value=choice_index;
946                 }
947
948                 choicetree=proto_item_add_subtree(choiceitem, ett_index);
949
950                 if(display_internal_per_fields){
951                         etr=choicetree;
952                 }
953
954                 /* find and call the appropriate callback */
955                 for(i=0;choice[i].name;i++){
956                         if(choice[i].value==(int)choice_index){
957                                 if(choice[i].func){
958                                         offset=choice[i].func(tvb, offset, pinfo, choicetree);
959                                         break;
960                                 } else {
961                                         NOT_DECODED_YET(choice[i].name);
962                                         break;
963                                 }
964                         }
965                 }
966                 proto_item_set_len(choiceitem, (offset>>3)!=(choice_offset>>3)?(offset>>3)-(choice_offset>>3):1);
967         } else {
968                 guint32 length;
969                 int i, index;
970                 guint32 choice_offset;
971                 proto_tree *choicetree;
972                 proto_item *choiceitem;
973                 proto_tree *etr=NULL;
974
975                 if(display_internal_per_fields){
976                         etr=tr;
977                 }
978
979                 /* 22.8 */
980                 offset=dissect_per_normally_small_nonnegative_whole_number(tvb, offset, pinfo, etr, hf_per_choice_extension, &choice_index);
981                 offset=dissect_per_length_determinant(tvb, offset, pinfo, etr, hf_per_open_type_length, &length);
982
983
984                 choice_offset=offset;
985                 choiceitem=proto_tree_add_text(tr, tvb, offset>>3, 0, "Choice");
986                 choicetree=proto_item_add_subtree(choiceitem, ett_index);
987
988                 index=-1;
989                 for(i=0;choice[i].name;i++){
990                         if(choice[i].extension==NOT_EXTENSION_ROOT){
991                                 if(!choice_index){
992                                         index=i;
993                                         break;
994                                 }
995                                 choice_index--;
996                         }
997                 }
998                 if(index!=-1){
999                         if(value){
1000                                 *value=choice_index;
1001                         }
1002                 }
1003
1004                 if(index==-1){
1005                         /* if we dont know how to decode this one, just step offset to the next structure */            
1006                         offset+=length*8;
1007                         NOT_DECODED_YET("unknown choice extension");
1008                 } else {
1009                         guint32 new_offset;
1010
1011                         proto_item_set_text(choiceitem, choice[index].name);
1012                         new_offset=choice[index].func(tvb, offset, pinfo, choicetree);
1013
1014                         if((new_offset>(offset+(length*8)))||((new_offset+8)<(offset+length*8))){
1015 printf("new_offset:%d  offset:%d  length*8:%d\n",new_offset,offset,length*8);
1016 /*                              g_assert_not_reached();*/
1017                         }
1018
1019                         offset+=length*8;
1020                 }
1021                 proto_item_set_len(choiceitem, (offset>>3)!=(choice_offset>>3)?(offset>>3)-(choice_offset>>3):1);
1022         }
1023
1024         proto_item_set_len(it, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1);
1025         return offset;
1026 }
1027
1028
1029 static char *
1030 index_get_optional_name(per_sequence_t *sequence, int index)
1031 {
1032         int i;
1033
1034         for(i=0;sequence[i].name;i++){
1035                 if((sequence[i].extension!=NOT_EXTENSION_ROOT)&&(sequence[i].optional==OPTIONAL)){
1036                         if(index==0){
1037                                 return sequence[i].name;
1038                         }
1039                         index--;
1040                 }
1041         }
1042         return "<unknown type>";
1043 }
1044
1045 static char *
1046 index_get_extension_name(per_sequence_t *sequence, int index)
1047 {
1048         int i;
1049
1050         for(i=0;sequence[i].name;i++){
1051                 if(sequence[i].extension==NOT_EXTENSION_ROOT){
1052                         if(index==0){
1053                                 return sequence[i].name;
1054                         }
1055                         index--;
1056                 }
1057         }
1058         return "<unknown type>";
1059 }
1060
1061 /* this functions decodes a SEQUENCE
1062    it can only handle SEQUENCES with at most 32 DEFAULT or OPTIONAL fields
1063 18.1 extension bit
1064 18.2 optinal/default items in root 
1065 18.3 we ignore the case where n>64K
1066 18.4 the root sequence
1067            18.5
1068            18.6
1069            18.7
1070            18.8
1071            18.9
1072 */
1073 guint32
1074 dissect_per_sequence(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, per_sequence_t *sequence)
1075 {
1076         gboolean extension_present, extension_flag, optional_field_flag;
1077         proto_item *item;
1078         proto_tree *tree;
1079         guint32 old_offset=offset;
1080         guint32 i, num_opts;
1081         guint32 optional_mask;
1082
1083
1084 DEBUG_ENTRY("dissect_per_sequence");
1085
1086         item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
1087         tree=proto_item_add_subtree(item, ett_index);
1088
1089
1090         /* first check if there should be an extension bit for this CHOICE.
1091            we do this by just checking the first choice arm 
1092          */
1093         /* 18.1 */
1094         extension_flag=0;
1095         if(sequence[0].extension==NO_EXTENSIONS){
1096                 extension_present=0;
1097         } else {
1098                 proto_tree *etr=NULL;
1099
1100                 if(display_internal_per_fields){
1101                         etr=tree;
1102                 }
1103                 extension_present=1;
1104                 offset=dissect_per_boolean(tvb, offset, pinfo, etr, hf_per_extension_bit, &extension_flag, NULL);
1105         }
1106         /* 18.2 */
1107         num_opts=0;
1108         for(i=0;sequence[i].name;i++){
1109                 if((sequence[i].extension!=NOT_EXTENSION_ROOT)&&(sequence[i].optional==OPTIONAL)){
1110                         num_opts++;
1111                 }
1112         }
1113
1114         optional_mask=0;
1115         for(i=0;i<num_opts;i++){
1116                 proto_item *it=NULL;
1117                 proto_tree *etr=NULL;
1118                 if(display_internal_per_fields){
1119                         etr=tree;
1120                 }
1121                 offset=dissect_per_boolean(tvb, offset, pinfo, etr, hf_per_optional_field_bit, &optional_field_flag, &it);
1122                 optional_mask<<=1;
1123                 if(optional_field_flag){
1124                         optional_mask|=0x01;
1125                 }
1126                 if(it){
1127                         proto_item_append_text(it, " (%s %s present)",
1128                                 index_get_optional_name(sequence, i),
1129                                 optional_field_flag?"is":"is NOT"
1130                                 );
1131                 }
1132         }
1133
1134
1135         /* 18.4 */
1136         for(i=0;sequence[i].name;i++){
1137                 if( (sequence[i].extension==NO_EXTENSIONS)
1138                 ||  (sequence[i].extension==EXTENSION_ROOT) ){
1139                         if(sequence[i].optional==OPTIONAL){
1140                                 gboolean is_present;
1141                                 is_present=(1<<(num_opts-1))&optional_mask;
1142                                 num_opts--;
1143                                 if(!is_present){
1144                                         continue;
1145                                 }
1146                         }
1147                         if(sequence[i].func){
1148                                 offset=sequence[i].func(tvb, offset, pinfo, tree);
1149                         } else {
1150                                 NOT_DECODED_YET(sequence[i].name);
1151                         }
1152                 }
1153         }
1154
1155
1156         if(extension_flag){
1157                 gboolean extension_bit;
1158                 guint32 num_known_extensions;
1159                 guint32 num_extensions;
1160                 guint32 extension_mask;
1161                 proto_tree *etr=NULL;
1162                 proto_item *it=NULL;
1163
1164                 if(display_internal_per_fields){
1165                         etr=tree;
1166                 }
1167
1168                 offset=dissect_per_normally_small_nonnegative_whole_number(tvb, offset, pinfo, etr, hf_per_num_sequence_extensions, &num_extensions);
1169                 /* the X.691 standard is VERY unclear here.
1170                    there is no mention that the lower bound lb for this
1171                    (apparently) semiconstrained value is 1,
1172                    apart from the NOTE: comment in 18.8 that this value can
1173                    not be 0.
1174                    In my book, there is a semantic difference between having
1175                    a comment that says that the value can not be zero
1176                    and stating that the lb is 1.
1177                    I dont know if this is right or not but it makes
1178                    some of the very few captures I have decode properly.
1179
1180                    It could also be that the captures I have are generated by 
1181                    a broken implementation.
1182                    If this is wrong and you dont report it as a bug
1183                    then it wont get fixed!
1184                 */
1185                 num_extensions+=1;
1186
1187                 extension_mask=0;
1188                 for(i=0;i<num_extensions;i++){
1189                         offset=dissect_per_boolean(tvb, offset, pinfo, etr, hf_per_extension_present_bit, &extension_bit, &it);
1190                         extension_mask=(extension_mask<<1)|extension_bit;
1191                         if(it){
1192                                 proto_item_append_text(it, " (%s %s present)",
1193                                         index_get_extension_name(sequence, i),
1194                                         extension_bit?"is":"is NOT"
1195                                         );
1196                         }
1197                         
1198                 }
1199
1200                 /* find how many extensions we know about */
1201                 num_known_extensions=0;
1202                 for(i=0;sequence[i].name;i++){
1203                         if(sequence[i].extension==NOT_EXTENSION_ROOT){
1204                                 num_known_extensions++;
1205                         }
1206                 }
1207
1208                 /* decode the extensions one by one */
1209                 for(i=0;i<num_extensions;i++){
1210                         guint32 length;
1211                         guint32 new_offset;
1212                         guint32 extension_index;
1213                         guint32 j,k;
1214
1215                         if(!((1L<<(num_extensions-1-i))&extension_mask)){
1216                                 /* this extension is not encoded in this PDU */
1217                                 continue;
1218                         }
1219
1220                         offset=dissect_per_length_determinant(tvb, offset, pinfo, etr, hf_per_open_type_length, &length);
1221
1222                         if(i>=num_known_extensions){
1223                                 /* we dont know how to decode this extension */
1224                                 offset+=length*8;
1225                                 NOT_DECODED_YET("unknown sequence extension");
1226                                 continue;
1227                         }
1228
1229                         extension_index=0;
1230                         for(j=0,k=0;sequence[j].name;j++){
1231                                 if(sequence[j].extension==NOT_EXTENSION_ROOT){
1232                                         if(k==i){
1233                                                 extension_index=j;
1234                                                 break;
1235                                         }
1236                                         k++;
1237                                 }
1238                         }
1239
1240                         if(sequence[extension_index].func){
1241                                 new_offset=sequence[extension_index].func(tvb, offset, pinfo, tree);
1242                         } else {
1243                                 NOT_DECODED_YET(sequence[extension_index].name);
1244                         }
1245                         offset+=length*8;
1246                         
1247                 }       
1248         }
1249
1250
1251         proto_item_set_len(item, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1);
1252         return offset;
1253 }
1254
1255
1256
1257
1258
1259 /* this fucntion dissects an OCTET STRING
1260         16.1
1261         16.2
1262         16.3
1263         16.4
1264         16.5
1265         16.6
1266         16.7
1267         16.8
1268
1269    max_len or min_len == -1 means there is no lower/upper constraint 
1270
1271    hf_index can either be a FT_BYTES or an FT_STRING
1272 */
1273 guint32
1274 dissect_per_octet_string(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
1275 {
1276         guint32 length;
1277         header_field_info *hfi;
1278
1279         hfi=proto_registrar_get_nth(hf_index);
1280
1281 DEBUG_ENTRY("dissect_per_octet_string");
1282         /* 16.5 if the length is 0 bytes there will be no encoding */
1283         if(max_len==0){
1284                 return offset;
1285         }
1286
1287
1288         if(min_len==-1){
1289                 min_len=0;
1290         }
1291
1292         /* 16.6 if length is fixed and less than or equal to two bytes*/
1293         if((min_len==max_len)&&(max_len<=2)){
1294                 static char bytes[4];
1295                 guint32 i, old_offset=offset;
1296                 gboolean bit;
1297
1298                 for(i=0;i<8;i++){
1299                         offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
1300                         bytes[0]=(bytes[0]<<1)|bit;
1301                 }
1302                 if(min_len==2){
1303                         for(i=0;i<8;i++){
1304                                 offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
1305                                 bytes[1]=(bytes[1]<<1)|bit;
1306                         }
1307                 }
1308
1309                 if(hfi->type==FT_STRING){
1310                         proto_tree_add_string(tree, hf_index, tvb, old_offset>>3, min_len+(offset&0x07)?1:0, bytes);
1311                 } else {
1312                         proto_tree_add_bytes(tree, hf_index, tvb, old_offset>>3, min_len+(offset&0x07)?1:0, bytes);
1313                 }
1314                 return offset;
1315         }
1316
1317
1318         /* aligne to byte */
1319         if(offset&0x07){
1320                 offset=(offset&0xfffffff8)+8;
1321         }
1322
1323         /* 16.7 if length is fixed and less than to 64k*/
1324         if((min_len==max_len)&&(min_len<65536)){
1325                 if(hfi->type==FT_STRING){
1326                         proto_tree_add_string(tree, hf_index, tvb, offset>>3, min_len, tvb_get_ptr(tvb, offset>>3, min_len));
1327                 } else {
1328                         proto_tree_add_bytes(tree, hf_index, tvb, offset>>3, min_len, tvb_get_ptr(tvb, offset>>3, min_len));
1329                 }
1330                 offset+=min_len*8;
1331                 return offset;
1332         }
1333
1334         /* 16.8 */
1335         if(max_len>0){
1336                 offset=dissect_per_constrained_integer(tvb, offset, pinfo, 
1337                         tree, hf_per_octet_string_length, min_len, max_len, 
1338                         &length, NULL, FALSE);
1339         } else {
1340                 offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_per_octet_string_length, &length);
1341         }
1342         if(length){
1343                 if(hfi->type==FT_STRING){
1344                         proto_tree_add_string(tree, hf_index, tvb, offset>>3, length, tvb_get_ptr(tvb, offset>>3, length));
1345                 } else {
1346                         proto_tree_add_bytes(tree, hf_index, tvb, offset>>3, length, tvb_get_ptr(tvb, offset>>3, length));
1347                 }
1348         }
1349         offset+=length*8;
1350
1351         return offset;
1352 }
1353
1354
1355
1356 void
1357 proto_register_per(void)
1358 {
1359         static hf_register_info hf[] =
1360         {
1361         { &hf_per_num_sequence_extensions,
1362                 { "Number of Sequence Extensions", "per.num_sequence_extensions", FT_UINT32, BASE_DEC,
1363                 NULL, 0, "Number of extensions encoded in this sequence", HFILL }},
1364         { &hf_per_choice_extension,
1365                 { "Choice Extension", "per.choice_extension", FT_UINT32, BASE_DEC,
1366                 NULL, 0, "Which extension of the Choice is encoded", HFILL }},
1367         { &hf_per_GeneralString_length,
1368                 { "GeneralString Length", "per.generalstring_length", FT_UINT32, BASE_DEC,
1369                 NULL, 0, "Length of the GeneralString", HFILL }},
1370         { &hf_per_extension_bit,
1371                 { "Extension Bit", "per.extension_bit", FT_BOOLEAN, 8,
1372                 TFS(&tfs_extension_bit), 0x01, "The extension bit of an aggregate", HFILL }},
1373         { &hf_per_extension_present_bit,
1374                 { "Extension Present Bit", "per.extension_present_bit", FT_BOOLEAN, 8,
1375                 TFS(&tfs_extension_present_bit), 0x01, "Whether this optional extension is present or not", HFILL }},
1376         { &hf_per_small_number_bit,
1377                 { "Small Number Bit", "per.small_number_bit", FT_BOOLEAN, 8,
1378                 TFS(&tfs_small_number_bit), 0x01, "The small number bit for a section 10.6 integer", HFILL }},
1379         { &hf_per_optional_field_bit,
1380                 { "Optional Field Bit", "per.optional_field_bit", FT_BOOLEAN, 8,
1381                 TFS(&tfs_optional_field_bit), 0x01, "This bit specifies the presence/absence of an optional field", HFILL }},
1382         { &hf_per_sequence_of_length,
1383                 { "Sequence-Of Length", "per.sequence_of_length", FT_UINT32, BASE_DEC,
1384                 NULL, 0, "Number of items in the Sequence Of", HFILL }},
1385         { &hf_per_object_identifier_length,
1386                 { "Object Length", "per.object_length", FT_UINT32, BASE_DEC,
1387                 NULL, 0, "Length of the object identifier", HFILL }},
1388         { &hf_per_open_type_length,
1389                 { "Open Type Length", "per.open_type_length", FT_UINT32, BASE_DEC,
1390                 NULL, 0, "Length of an open type encoding", HFILL }},
1391         { &hf_per_octet_string_length,
1392                 { "Octet String Length", "per.octet_string_length", FT_UINT32, BASE_DEC,
1393                 NULL, 0, "Number of bytes in the Octet String", HFILL }},
1394         };
1395
1396         static gint *ett[] =
1397         {
1398                 &ett_per_sequence_of_item
1399         };
1400         module_t *per_module;
1401
1402         proto_per = proto_register_protocol("Packet Encoding Rules (ASN.1 X.691)", "PER", "per");
1403         proto_register_field_array(proto_per, hf, array_length(hf));
1404         proto_register_subtree_array(ett, array_length(ett));
1405
1406         per_module = prefs_register_protocol(proto_per, NULL);
1407         prefs_register_bool_preference(per_module, "display_internal_per_fields",
1408                 "Display the internal PER fields in the tree",
1409                 "Whether the dissector should put the internal PER data in the tree or if it should hide it",
1410                 &display_internal_per_fields);
1411
1412 }
1413
1414 void
1415 proto_reg_handoff_per(void)
1416 {
1417 }
1418