3 * Copyright 2005, Luis E. Garcia Ontanon <luis@ontanon.org>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/emem.h>
33 #include <epan/proto.h>
34 #include <epan/packet_info.h>
35 #include <epan/tvbparse.h>
38 #define TVBPARSE_DEBUG_ALL 0xffffffff
41 #define TVBPARSE_DEBUG_ 0x80000000
42 #define TVBPARSE_DEBUG_ 0x40000000
43 #define TVBPARSE_DEBUG_ 0x20000000
44 #define TVBPARSE_DEBUG_ 0x10000000
47 #define TVBPARSE_DEBUG_CHAR 0x08000000
48 #define TVBPARSE_DEBUG_CHARS 0x04000000
49 #define TVBPARSE_DEBUG_NOT_CHAR 0x02000000
50 #define TVBPARSE_DEBUG_NOT_CHARS 0x01000000
51 #define TVBPARSE_DEBUG_STRING 0x00800000
52 #define TVBPARSE_DEBUG_CASESTRING 0x00400000
53 #define TVBPARSE_DEBUG_ONEOF 0x00200000
54 #define TVBPARSE_DEBUG_HASH 0x00100000
55 #define TVBPARSE_DEBUG_SEQ 0x00080000
56 #define TVBPARSE_DEBUG_SOME 0x00040000
57 #define TVBPARSE_DEBUG_UNTIL 0x00020000
59 #define TVBPARSE_DEBUG_ 0x00010000
60 #define TVBPARSE_DEBUG_ 0x00008000
61 #define TVBPARSE_DEBUG_ 0x00004000
62 #define TVBPARSE_DEBUG_ 0x00002000
63 #define TVBPARSE_DEBUG_ 0x00001000
65 #define TVBPARSE_DEBUG_TT 0x00000800
66 #define TVBPARSE_DEBUG_CB 0x00000400
67 #define TVBPARSE_DEBUG_GET 0x00000200
68 #define TVBPARSE_DEBUG_FIND 0x00000100
69 #define TVBPARSE_DEBUG_NEWTOK 0x00000080
70 #define TVBPARSE_DEBUG_IGNORE 0x00000040
71 #define TVBPARSE_DEBUG_PEEK 0x00000020
73 #define TVBPARSE_DEBUG_ 0x00000010
74 #define TVBPARSE_DEBUG_ 0x00000008
75 #define TVBPARSE_DEBUG_ 0x00000004
76 #define TVBPARSE_DEBUG_ 0x00000002
77 #define TVBPARSE_DEBUG_ 0x00000001
81 #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
84 static tvbparse_elem_t
* new_tok(tvbparse_t
* tt
,
88 const tvbparse_wanted_t
* wanted
) {
92 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_NEWTOK
) g_warning("new_tok: id=%i offset=%u len=%u",id
,offset
,len
);
95 tok
= (tvbparse_elem_t
*)ep_alloc(sizeof(tvbparse_elem_t
));
104 tok
->wanted
= wanted
;
110 static int ignore_fcn(tvbparse_t
* tt
, int offset
) {
113 tvbparse_elem_t
* ignored
= NULL
;
115 if (!tt
->ignore
) return 0;
117 #ifdef TVBPARSE_DEBUG
118 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_IGNORE
) g_warning("ignore: enter");
121 while ((consumed
= tt
->ignore
->condition(tt
,offset
,tt
->ignore
,&ignored
)) > 0) {
124 #ifdef TVBPARSE_DEBUG
125 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_IGNORE
) g_warning("ignore: consumed=%i",consumed
);
130 #ifdef TVBPARSE_DEBUG
131 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_IGNORE
) g_warning("ignore: len=%i",len
);
138 static int cond_char (tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
142 #ifdef TVBPARSE_DEBUG
143 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CHAR
) g_warning("cond_char: control='%s'",wanted
->control
.str
);
146 if ( offset
+ 1 > tt
->end_offset
)
149 t
= (gchar
) tvb_get_guint8(tt
->tvb
,offset
);
151 for(i
= 0; (c
= wanted
->control
.str
[i
]) && offset
<= tt
->end_offset
; i
++) {
153 *tok
= new_tok(tt
,wanted
->id
,offset
,1,wanted
);
154 #ifdef TVBPARSE_DEBUG
155 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CHAR
) g_warning("cond_char: GOT: '%c'",c
);
164 tvbparse_wanted_t
* tvbparse_char(const int id
,
167 tvbparse_action_t before_cb
,
168 tvbparse_action_t after_cb
) {
169 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
171 w
->condition
= cond_char
;
173 w
->control
.str
= chr
;
176 w
->before
= before_cb
;
182 static int cond_chars (tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
185 int left
= tt
->end_offset
- offset
;
187 #ifdef TVBPARSE_DEBUG
188 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CHARS
) g_warning("cond_chars: control='%s'",wanted
->control
.str
);
191 if ( offset
+ (int)wanted
->min
> tt
->end_offset
)
194 left
= left
< (int) wanted
->max
? left
: (int) wanted
->max
;
197 gchar t
= (gchar
) tvb_get_guint8(tt
->tvb
,offset
++);
201 while ( (c
= wanted
->control
.str
[i
++]) ) {
202 if (c
== t
) goto next_char
;
212 if (length
< wanted
->min
) {
215 *tok
= new_tok(tt
,wanted
->id
,start
,length
,wanted
);
216 #ifdef TVBPARSE_DEBUG
217 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CHARS
) g_warning("cond_chars: GOT len=%i",length
);
223 tvbparse_wanted_t
* tvbparse_chars(const int id
,
228 tvbparse_action_t before_cb
,
229 tvbparse_action_t after_cb
) {
230 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
232 w
->condition
= cond_chars
;
234 w
->control
.str
= chr
;
235 w
->min
= min_len
? min_len
: 1;
236 w
->max
= max_len
? max_len
: G_MAXINT
/2;
238 w
->before
= before_cb
;
245 static int cond_not_char(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
248 gboolean not_matched
= FALSE
;
250 #ifdef TVBPARSE_DEBUG
251 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_NOT_CHAR
) g_warning("cond_not_char: control='%s'",wanted
->control
.str
);
254 if (! offset
< tt
->end_offset
) {
258 t
= (gchar
) tvb_get_guint8(tt
->tvb
,offset
);
260 for(i
= 0; (c
= wanted
->control
.str
[i
]); i
++) {
269 *tok
= new_tok(tt
,wanted
->id
,offset
,1,wanted
);
270 #ifdef TVBPARSE_DEBUG
271 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_NOT_CHAR
) g_warning("cond_not_char: GOT='%c'",t
);
277 tvbparse_wanted_t
* tvbparse_not_char(const int id
,
280 tvbparse_action_t before_cb
,
281 tvbparse_action_t after_cb
) {
282 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
284 w
->condition
= cond_not_char
;
286 w
->control
.str
= chr
;
288 w
->before
= before_cb
;
294 static int cond_not_chars(tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
296 int left
= tt
->end_offset
- offset
;
299 #ifdef TVBPARSE_DEBUG
300 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_NOT_CHARS
) g_warning("cond_not_chars: control='%s'",wanted
->control
.str
);
303 if ( offset
+ (int)wanted
->min
> tt
->end_offset
)
306 if (left
< (int)wanted
->min
)
309 left
= left
<= (int)wanted
->max
? left
: (int)wanted
->max
;
313 gchar t
= (gchar
) tvb_get_guint8(tt
->tvb
,offset
);
316 while ( (c
= wanted
->control
.str
[i
++]) ) {
317 if (c
== t
) goto end_not_chars
;
326 if ( length
< wanted
->min
) {
329 *tok
= new_tok(tt
,wanted
->id
,start
,length
,wanted
);
330 #ifdef TVBPARSE_DEBUG
331 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_NOT_CHARS
) g_warning("cond_not_chars: GOT len=%i",length
);
337 tvbparse_wanted_t
* tvbparse_not_chars(const int id
,
342 tvbparse_action_t before_cb
,
343 tvbparse_action_t after_cb
){
344 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
346 w
->condition
= cond_not_chars
;
348 w
->control
.str
= chr
;
350 w
->min
= min_len
? min_len
: 1;
351 w
->max
= max_len
? max_len
: G_MAXINT
/2;
353 w
->before
= before_cb
;
360 static int cond_string(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
361 int len
= wanted
->len
;
362 #ifdef TVBPARSE_DEBUG
363 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_STRING
) g_warning("cond_string: control='%s'",wanted
->control
.str
);
366 if ( offset
+ wanted
->len
> tt
->end_offset
)
369 if ( tvb_strneql(tt
->tvb
, offset
, wanted
->control
.str
, len
) == 0 ) {
370 *tok
= new_tok(tt
,wanted
->id
,offset
,len
,wanted
);
371 #ifdef TVBPARSE_DEBUG
372 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_STRING
) g_warning("cond_string: GOT len=%i",len
);
380 tvbparse_wanted_t
* tvbparse_string(const int id
,
383 tvbparse_action_t before_cb
,
384 tvbparse_action_t after_cb
) {
385 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
387 w
->condition
= cond_string
;
389 w
->control
.str
= str
;
390 w
->len
= (int) strlen(str
);
392 w
->before
= before_cb
;
398 static int cond_casestring(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
399 int len
= wanted
->len
;
400 #ifdef TVBPARSE_DEBUG
401 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CASESTRING
) g_warning("cond_casestring: control='%s'",wanted
->control
.str
);
404 if ( offset
+ len
> tt
->end_offset
)
407 if ( tvb_strncaseeql(tt
->tvb
, offset
, wanted
->control
.str
, len
) == 0 ) {
408 *tok
= new_tok(tt
,wanted
->id
,offset
,len
,wanted
);
409 #ifdef TVBPARSE_DEBUG
410 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CASESTRING
) g_warning("cond_casestring: GOT len=%i",len
);
419 tvbparse_wanted_t
* tvbparse_casestring(const int id
,
422 tvbparse_action_t before_cb
,
423 tvbparse_action_t after_cb
) {
424 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
426 w
->condition
= cond_casestring
;
428 w
->control
.str
= str
;
429 w
->len
= (int) strlen(str
);
431 w
->before
= before_cb
;
437 static int cond_one_of(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
439 #ifdef TVBPARSE_DEBUG
440 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_ONEOF
) g_warning("cond_one_of: START");
443 if ( offset
> tt
->end_offset
)
446 for(i
=0; i
< wanted
->control
.elems
->len
; i
++) {
447 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_ptr_array_index(wanted
->control
.elems
,i
);
448 tvbparse_elem_t
* new_elem
= NULL
;
451 if ( offset
+ w
->len
> tt
->end_offset
)
454 curr_len
= w
->condition(tt
, offset
, w
, &new_elem
);
457 *tok
= new_tok(tt
, wanted
->id
, new_elem
->offset
, new_elem
->len
, wanted
);
458 (*tok
)->sub
= new_elem
;
459 #ifdef TVBPARSE_DEBUG
460 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_ONEOF
) g_warning("cond_one_of: GOT len=%i",curr_len
);
469 tvbparse_wanted_t
* tvbparse_set_oneof(const int id
,
471 tvbparse_action_t before_cb
,
472 tvbparse_action_t after_cb
,
474 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
478 w
->condition
= cond_one_of
;
481 w
->before
= before_cb
;
483 w
->control
.elems
= g_ptr_array_new();
485 va_start(ap
,after_cb
);
487 while(( el
= va_arg(ap
,tvbparse_t
*) )) {
488 g_ptr_array_add(w
->control
.elems
,el
);
496 static int cond_hash(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
499 tvbparse_elem_t
* key_elem
= NULL
;
500 tvbparse_wanted_t
* value_wanted
= NULL
;
502 tvbparse_elem_t
* value_elem
= NULL
;
504 tvbparse_elem_t
* ret_tok
;
506 #ifdef TVBPARSE_DEBUG
507 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_HASH
) g_warning("cond_hash: START");
510 if ( offset
> tt
->end_offset
)
513 key_len
= wanted
->control
.hash
.key
->condition(tt
, offset
, wanted
->control
.hash
.key
, &key_elem
);
518 key
= tvb_get_string(wmem_packet_scope(),key_elem
->tvb
,key_elem
->offset
,key_elem
->len
);
519 #ifdef TVBPARSE_DEBUG
520 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_HASH
) g_warning("cond_hash: got key='%s'",key
);
523 if ((value_wanted
= (tvbparse_wanted_t
*)g_hash_table_lookup(wanted
->control
.hash
.table
,key
))) {
524 value_len
= value_wanted
->condition(tt
, offset
+ key_len
, value_wanted
, &value_elem
);
525 } else if (wanted
->control
.hash
.other
) {
526 value_len
= wanted
->control
.hash
.other
->condition(tt
, offset
+key_len
, wanted
->control
.hash
.other
, &value_elem
);
533 tot_len
= key_len
+ value_len
;
535 ret_tok
= new_tok(tt
, value_elem
->id
, offset
, tot_len
, wanted
);
536 ret_tok
->sub
= key_elem
;
537 ret_tok
->sub
->last
->next
= value_elem
;
540 #ifdef TVBPARSE_DEBUG
541 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_HASH
) g_warning("cond_hash: GOT len=%i",tot_len
);
547 tvbparse_wanted_t
* tvbparse_hashed(const int id
,
549 tvbparse_action_t before_cb
,
550 tvbparse_action_t after_cb
,
551 tvbparse_wanted_t
* key
,
552 tvbparse_wanted_t
* other
,
554 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
556 tvbparse_wanted_t
* el
;
559 w
->condition
= cond_hash
;
562 w
->before
= before_cb
;
564 w
->control
.hash
.table
= g_hash_table_new(g_str_hash
,g_str_equal
);
565 w
->control
.hash
.key
= key
;
566 w
->control
.hash
.other
= other
;
570 while(( name
= va_arg(ap
,gchar
*) )) {
571 el
= va_arg(ap
,tvbparse_wanted_t
*);
572 g_hash_table_insert(w
->control
.hash
.table
,name
,el
);
580 void tvbparse_hashed_add(tvbparse_wanted_t
* w
, ...) {
581 tvbparse_wanted_t
* el
;
587 while (( name
= va_arg(ap
,gchar
*) )) {
588 el
= va_arg(ap
,tvbparse_wanted_t
*);
589 g_hash_table_insert(w
->control
.hash
.table
,name
,el
);
595 static int cond_seq(tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
599 tvbparse_elem_t
* ret_tok
= NULL
;
601 if ( offset
> tt
->end_offset
)
603 #ifdef TVBPARSE_DEBUG
604 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SEQ
) g_warning("cond_seq: START");
607 for(i
=0; i
< wanted
->control
.elems
->len
; i
++) {
608 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_ptr_array_index(wanted
->control
.elems
,i
);
609 tvbparse_elem_t
* new_elem
= NULL
;
611 if ( offset
+ w
->len
> tt
->end_offset
)
615 len
= w
->condition(tt
, offset
, w
, &new_elem
);
619 ret_tok
->len
= (new_elem
->offset
- ret_tok
->offset
) + new_elem
->len
;
620 ret_tok
->sub
->last
->next
= new_elem
;
621 ret_tok
->sub
->last
= new_elem
;
623 ret_tok
= new_tok(tt
, wanted
->id
, new_elem
->offset
, new_elem
->len
, wanted
);
624 ret_tok
->sub
= new_elem
;
625 new_elem
->last
= new_elem
;
632 offset
+= ignore_fcn(tt
,offset
);
637 #ifdef TVBPARSE_DEBUG
638 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SEQ
) g_warning("cond_seq: GOT len=%i",offset
- start
);
641 return offset
- start
;
645 tvbparse_wanted_t
* tvbparse_set_seq(const int id
,
647 tvbparse_action_t before_cb
,
648 tvbparse_action_t after_cb
,
650 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
651 tvbparse_wanted_t
* el
= NULL
;
654 w
->condition
= cond_seq
;
657 w
->before
= before_cb
;
659 w
->control
.elems
= g_ptr_array_new();
661 va_start(ap
,after_cb
);
663 while(( el
= va_arg(ap
,tvbparse_wanted_t
*) )) {
664 g_ptr_array_add(w
->control
.elems
,el
);
671 static int cond_some(tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
672 guint got_so_far
= 0;
674 tvbparse_elem_t
* ret_tok
= NULL
;
675 #ifdef TVBPARSE_DEBUG
676 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SOME
) g_warning("cond_some: START");
679 if ( offset
> tt
->end_offset
)
682 if ( wanted
->min
== 0 ) {
683 ret_tok
= new_tok(tt
,wanted
->id
,offset
,0,wanted
);
686 while (got_so_far
< wanted
->max
) {
687 tvbparse_elem_t
* new_elem
= NULL
;
690 if ( offset
> tt
->end_offset
)
693 consumed
= wanted
->control
.subelem
->condition(tt
, offset
, wanted
->control
.subelem
, &new_elem
);
697 ret_tok
->len
= (new_elem
->offset
- ret_tok
->offset
) + new_elem
->len
;
700 ret_tok
->sub
->last
->next
= new_elem
;
701 ret_tok
->sub
->last
= new_elem
;
703 ret_tok
->sub
= new_elem
;
706 ret_tok
= new_tok(tt
, wanted
->id
, new_elem
->offset
, new_elem
->len
, wanted
);
707 ret_tok
->sub
= new_elem
;
717 #ifdef TVBPARSE_DEBUG
718 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SOME
) g_warning("cond_some: got num=%u",got_so_far
);
721 if(got_so_far
< wanted
->min
) {
726 #ifdef TVBPARSE_DEBUG
727 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SOME
) g_warning("cond_some: GOT len=%i",offset
- start
);
729 return offset
- start
;
732 tvbparse_wanted_t
* tvbparse_some(const int id
,
736 tvbparse_action_t before_cb
,
737 tvbparse_action_t after_cb
,
738 const tvbparse_wanted_t
* el
) {
740 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
742 g_assert(from
<= to
);
744 w
->condition
= cond_some
;
749 w
->before
= before_cb
;
751 w
->control
.subelem
= el
;
757 static int cond_until(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
758 tvbparse_elem_t
* new_elem
= NULL
;
760 int target_offset
= offset
;
761 #ifdef TVBPARSE_DEBUG
762 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_UNTIL
) g_warning("cond_until: START");
765 if ( offset
+ wanted
->control
.until
.subelem
->len
> tt
->end_offset
)
769 len
= wanted
->control
.until
.subelem
->condition(tt
, target_offset
++, wanted
->control
.until
.subelem
, &new_elem
);
770 } while(len
< 0 && target_offset
+1 < tt
->end_offset
);
774 new_elem
->id
= wanted
->id
;
775 new_elem
->next
= NULL
;
776 new_elem
->last
= NULL
;
777 new_elem
->wanted
= wanted
;
778 new_elem
->offset
= offset
;
782 switch (wanted
->control
.until
.mode
) {
783 case TP_UNTIL_INCLUDE
:
784 new_elem
->len
= target_offset
- offset
- 1 + len
;
785 #ifdef TVBPARSE_DEBUG
786 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_UNTIL
) g_warning("cond_until: GOT len=%i",target_offset
- offset
-1 + len
);
788 return target_offset
- offset
-1 + len
;
790 new_elem
->len
= target_offset
- offset
- 1;
791 #ifdef TVBPARSE_DEBUG
792 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_UNTIL
) g_warning("cond_until: GOT len=%i",target_offset
- offset
-1 + len
);
794 return target_offset
- offset
- 1 + len
;
796 new_elem
->len
= target_offset
- offset
- 1;
797 #ifdef TVBPARSE_DEBUG
798 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_UNTIL
) g_warning("cond_until: GOT len=%i",target_offset
- offset
-1);
800 return target_offset
- offset
-1;
802 DISSECTOR_ASSERT_NOT_REACHED();
811 tvbparse_wanted_t
* tvbparse_until(const int id
,
813 tvbparse_action_t before_cb
,
814 tvbparse_action_t after_cb
,
815 const tvbparse_wanted_t
* el
,
816 until_mode_t until_mode
) {
817 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
819 w
->condition
= cond_until
;
820 w
->control
.until
.mode
= until_mode
;
821 w
->control
.until
.subelem
= el
;
824 w
->before
= before_cb
;
830 static int cond_handle(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
831 tvbparse_wanted_t
* w
= *(wanted
->control
.handle
);
832 int len
= w
->condition(tt
, offset
, w
, tok
);
841 tvbparse_wanted_t
* tvbparse_handle(tvbparse_wanted_t
** handle
) {
842 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
844 w
->condition
= cond_handle
;
845 w
->control
.handle
= handle
;
850 static int cond_end(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted _U_
, tvbparse_elem_t
** tok
) {
851 if (offset
== tt
->end_offset
) {
852 *tok
= new_tok(tt
,wanted
->id
,offset
,0,wanted
);
859 tvbparse_wanted_t
* tvbparse_end_of_buffer(const int id
,
861 tvbparse_action_t before_cb
,
862 tvbparse_action_t after_cb
) {
863 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_malloc0(sizeof(tvbparse_wanted_t
));
866 w
->condition
= cond_end
;
868 w
->before
= before_cb
;
876 /* these extract binary values */
878 static int cond_ft(tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
881 if ( offset
+ wanted
->len
> tt
->end_offset
)
886 } else if (wanted
->control
.ftenum
== FT_STRINGZ
) {
887 if (( len
= tvb_find_guint8(tt
->tvb
,offset
,tt
->end_offset
- offset
,'\0') >= 0 )) {
888 *tok
= new_tok(tt
,wanted
->id
,offset
,len
,wanted
);
898 gint ft_lens
[] = {-1,-1,-1, 1, 2, 3, 4, 8, 1, 2, 3, 4, 8, 4, 8,-1,-1,-1, 0, -1, 6, -1, -1, 4, sizeof(struct e_in6_addr
), -1, -1, -1, -1 };
900 tvbparse_wanted_t
* tvbparse_ft(int id
,
902 tvbparse_action_t before_cb
,
903 tvbparse_action_t after_cb
,
904 enum ftenum ftenum
) {
905 gint len
= ft_lens
[ftenum
];
908 tvbparse_wanted_t
* w
= g_malloc0(sizeof(tvbparse_wanted_t
));
911 w
->condition
= cond_ft
;
913 w
->control
.ftenum
= ftenum
;
915 w
->before
= before_cb
;
920 g_assert(! "unsupported ftenum" );
925 static int cond_ft_comp(tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted _U_
, tvbparse_elem_t
** tok
) {
926 void* l
= wanted
->control
.number
.extract(tt
->tvb
,offset
);
927 const void* r
= &(wanted
->control
.number
.value
);
929 if ( offset
+ wanted
->len
> tt
->end_offset
)
932 if ( wanted
->control
.number
.comp(&l
,&r
) ) {
933 *tok
= new_tok(tt
,wanted
->id
,offset
,wanted
->len
,wanted
);
940 static gboolean
comp_gt_i(void* lp
, const void* rp
) { return ( *((gint64
*)lp
) > *((gint64
*)rp
) ); }
941 static gboolean
comp_ge_i(void* lp
, const void* rp
) { return ( *((gint64
*)lp
) >= *((gint64
*)rp
) ); }
942 static gboolean
comp_eq_i(void* lp
, const void* rp
) { return ( *((gint64
*)lp
) == *((gint64
*)rp
) ); }
943 static gboolean
comp_ne_i(void* lp
, const void* rp
) { return ( *((gint64
*)lp
) != *((gint64
*)rp
) ); }
944 static gboolean
comp_le_i(void* lp
, const void* rp
) { return ( *((gint64
*)lp
) <= *((gint64
*)rp
) ); }
945 static gboolean
comp_lt_i(void* lp
, const void* rp
) { return ( *((gint64
*)lp
) < *((gint64
*)rp
) ); }
947 static gboolean
comp_gt_u(void* lp
, const void* rp
) { return ( *((guint64
*)lp
) > *((guint64
*)rp
) ); }
948 static gboolean
comp_ge_u(void* lp
, const void* rp
) { return ( *((guint64
*)lp
) >= *((guint64
*)rp
) ); }
949 static gboolean
comp_eq_u(void* lp
, const void* rp
) { return ( *((guint64
*)lp
) == *((guint64
*)rp
) ); }
950 static gboolean
comp_ne_u(void* lp
, const void* rp
) { return ( *((guint64
*)lp
) != *((guint64
*)rp
) ); }
951 static gboolean
comp_le_u(void* lp
, const void* rp
) { return ( *((guint64
*)lp
) <= *((guint64
*)rp
) ); }
952 static gboolean
comp_lt_u(void* lp
, const void* rp
) { return ( *((guint64
*)lp
) < *((guint64
*)rp
) ); }
954 static gboolean
comp_gt_f(void* lp
, const void* rp
) { return ( *((gdouble
*)lp
) > *((gdouble
*)rp
) ); }
955 static gboolean
comp_ge_f(void* lp
, const void* rp
) { return ( *((gdouble
*)lp
) >= *((gdouble
*)rp
) ); }
956 static gboolean
comp_eq_f(void* lp
, const void* rp
) { return ( *((gdouble
*)lp
) == *((gdouble
*)rp
) ); }
957 static gboolean
comp_ne_f(void* lp
, const void* rp
) { return ( *((gdouble
*)lp
) != *((gdouble
*)rp
) ); }
958 static gboolean
comp_le_f(void* lp
, const void* rp
) { return ( *((gdouble
*)lp
) <= *((gdouble
*)rp
) ); }
959 static gboolean
comp_lt_f(void* lp
, const void* rp
) { return ( *((gdouble
*)lp
) < *((gdouble
*)rp
) ); }
961 static void* extract_u8(tvbuff_t
* tvb
, guint offset
) {
962 guint64
* p
= ep_new(guint64
);
963 *p
= tvb_get_guint8(tvb
,offset
);
967 static void* extract_uns(tvbuff_t
* tvb
, guint offset
) {
968 guint64
* p
= ep_new(guint64
);
969 *p
= tvb_get_ntohs(tvb
,offset
);
973 static void* extract_un24(tvbuff_t
* tvb
, guint offset
) {
974 guint64
* p
= ep_new(guint64
);
975 *p
= tvb_get_ntoh24(tvb
,offset
);
979 static void* extract_unl(tvbuff_t
* tvb
, guint offset
) {
980 guint64
* p
= ep_new(guint64
);
981 *p
= tvb_get_ntohl(tvb
,offset
);
985 static void* extract_un64(tvbuff_t
* tvb
, guint offset
) {
986 guint64
* p
= ep_new(guint64
);
987 *p
= tvb_get_ntoh64(tvb
,offset
);
991 static void* extract_ules(tvbuff_t
* tvb
, guint offset
) {
992 guint64
* p
= ep_new(guint64
);
993 *p
= tvb_get_letohs(tvb
,offset
);
997 static void* extract_ule24(tvbuff_t
* tvb
, guint offset
) {
998 guint64
* p
= ep_new(guint64
);
999 *p
= tvb_get_letoh24(tvb
,offset
);
1003 static void* extract_ulel(tvbuff_t
* tvb
, guint offset
) {
1004 guint64
* p
= ep_new(guint64
);
1005 *p
= tvb_get_letohl(tvb
,offset
);
1009 static void* extract_ule64(tvbuff_t
* tvb
, guint offset
) {
1010 guint64
* p
= ep_new(guint64
);
1011 *p
= tvb_get_letoh64(tvb
,offset
);
1015 static void* extract_ins(tvbuff_t
* tvb
, guint offset
) {
1016 guint64
* p
= ep_new(guint64
);
1017 *p
= tvb_get_ntohs(tvb
,offset
);
1021 static void* extract_in24(tvbuff_t
* tvb
, guint offset
) {
1022 guint64
* p
= ep_new(guint64
);
1023 *p
= tvb_get_ntoh24(tvb
,offset
);
1027 static void* extract_inl(tvbuff_t
* tvb
, guint offset
) {
1028 guint64
* p
= ep_new(guint64
);
1029 *p
= tvb_get_ntohl(tvb
,offset
);
1033 static void* extract_in64(tvbuff_t
* tvb
, guint offset
) {
1034 guint64
* p
= ep_new(guint64
);
1035 *p
= tvb_get_ntoh64(tvb
,offset
);
1039 static void* extract_iles(tvbuff_t
* tvb
, guint offset
) {
1040 guint64
* p
= ep_new(guint64
);
1041 *p
= tvb_get_letohs(tvb
,offset
);
1045 static void* extract_ile24(tvbuff_t
* tvb
, guint offset
) {
1046 guint64
* p
= ep_new(guint64
);
1047 *p
= tvb_get_letoh24(tvb
,offset
);
1051 static void* extract_ilel(tvbuff_t
* tvb
, guint offset
) {
1052 guint64
* p
= ep_new(guint64
);
1053 *p
= tvb_get_letohl(tvb
,offset
);
1057 static void* extract_ile64(tvbuff_t
* tvb
, guint offset
) {
1058 guint64
* p
= ep_new(guint64
);
1059 *p
= tvb_get_letoh64(tvb
,offset
);
1063 static void* extract_inf(tvbuff_t
* tvb
, guint offset
) {
1064 gdouble
* p
= ep_new(gdouble
);
1065 *p
= tvb_get_ntohieee_float(tvb
,offset
);
1069 static void* extract_ind(tvbuff_t
* tvb
, guint offset
) {
1070 gdouble
* p
= ep_new(gdouble
);
1071 *p
= tvb_get_ntohieee_double(tvb
,offset
);
1075 static void* extract_ilef(tvbuff_t
* tvb
, guint offset
) {
1076 gdouble
* p
= ep_new(gdouble
);
1077 *p
= tvb_get_letohieee_float(tvb
,offset
);
1081 static void* extract_iled(tvbuff_t
* tvb
, guint offset
) {
1082 gdouble
* p
= ep_new(gdouble
);
1083 *p
= tvb_get_letohieee_double(tvb
,offset
);
1089 static gboolean (*comps_u
[])(void*, const void*) = {comp_gt_u
,comp_ge_u
,comp_eq_u
,comp_ne_u
,comp_le_u
,comp_lt_u
};
1090 static gboolean (*comps_i
[])(void*, const void*) = {comp_gt_i
,comp_ge_i
,comp_eq_i
,comp_ne_i
,comp_le_i
,comp_lt_i
};
1091 static gboolean (*comps_f
[])(void*, const void*) = {comp_gt_f
,comp_ge_f
,comp_eq_f
,comp_ne_f
,comp_le_f
,comp_lt_f
};
1093 static gboolean (**comps
[])(void*, const void*) = {comps_u
,comps_i
,comps_f
};
1095 static void* (*extract_n
[])(tvbuff_t
* tvb
, guint offset
) = {
1096 NULL
, NULL
, NULL
, extract_u8
, extract_uns
, extract_un24
, extract_unl
,
1097 extract_un64
, extract_u8
, extract_ins
, extract_in24
, extract_inl
,
1098 extract_in64
, extract_inf
, extract_ind
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
1099 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,NULL
, NULL
1101 static void* (*extract_le
[])(tvbuff_t
* tvb
, guint offset
) = {
1102 NULL
, NULL
, NULL
, extract_u8
, extract_ules
, extract_ule24
, extract_ulel
,
1103 extract_ule64
, extract_u8
, extract_iles
, extract_ile24
, extract_ilel
,
1104 extract_ile64
, extract_ilef
, extract_iled
, NULL
, NULL
, NULL
, NULL
, NULL
,
1105 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,NULL
, NULL
1108 static void* (**extracts
[])(tvbuff_t
* tvb
, guint offset
) = { extract_n
, extract_le
};
1111 tvbparse_wanted_t
* tvbparse_ft_numcmp(int id
,
1113 tvbparse_action_t before_cb
,
1114 tvbparse_action_t after_cb
,
1117 enum ft_cmp_op ft_cmp_op
,
1119 tvbparse_wanted_t
* w
= g_malloc0(sizeof(tvbparse_wanted_t
));
1122 va_start(ap
,ft_cmp_op
);
1129 w
->control
.number
.comp
= comps
[0][ft_cmp_op
];
1130 w
->control
.number
.value
.u
= va_arg(ap
,guint32
);
1133 w
->control
.number
.comp
= comps
[0][ft_cmp_op
];
1134 w
->control
.number
.value
.u
= va_arg(ap
,guint64
);
1140 w
->control
.number
.comp
= comps
[1][ft_cmp_op
];
1141 w
->control
.number
.value
.i
= va_arg(ap
,gint32
);
1144 w
->control
.number
.comp
= comps
[1][ft_cmp_op
];
1145 w
->control
.number
.value
.i
= va_arg(ap
,gint64
);
1149 w
->control
.number
.comp
= comps
[1][ft_cmp_op
];
1150 w
->control
.number
.value
.i
= va_arg(ap
,gdouble
);
1153 g_assert(! "comparison unsupported");
1156 w
->control
.number
.extract
= extracts
[little_endian
][ftenum
];
1158 g_assert(w
->control
.number
.extract
&& "extraction unsupported");
1161 w
->condition
= cond_ft_comp
;
1162 w
->after
= after_cb
;
1163 w
->before
= before_cb
;
1172 tvbparse_wanted_t
* tvbparse_quoted(const int id
,
1174 tvbparse_action_t before_cb
,
1175 tvbparse_action_t after_cb
,
1179 gchar
* esc_quot
= g_strdup_printf("%c%c",esc
,quote
);
1180 gchar
* quot
= g_strdup_printf("%c",quote
);
1181 tvbparse_wanted_t
* want_quot
= tvbparse_char(-1,quot
,NULL
,NULL
,NULL
);
1183 return tvbparse_set_oneof(id
, data
, before_cb
, after_cb
,
1184 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
1186 tvbparse_set_seq(-1,NULL
,NULL
,NULL
,
1187 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1188 tvbparse_string(-1,esc_quot
,NULL
,NULL
,NULL
),
1189 tvbparse_not_chars(-1,0,0,quot
,NULL
,NULL
,NULL
),
1194 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
1201 void tvbparse_shrink_token_cb(void* tvbparse_data _U_
,
1202 const void* wanted_data _U_
,
1203 tvbparse_elem_t
* tok
) {
1208 tvbparse_t
* tvbparse_init(tvbuff_t
* tvb
,
1212 const tvbparse_wanted_t
* ignore
) {
1213 tvbparse_t
* tt
= (tvbparse_t
*)ep_alloc(sizeof(tvbparse_t
));
1215 #ifdef TVBPARSE_DEBUG
1216 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_TT
) g_warning("tvbparse_init: offset=%i len=%i",offset
,len
);
1221 tt
->offset
= offset
;
1222 len
= (len
== -1) ? (int) tvb_length(tvb
) : len
;
1223 tt
->end_offset
= offset
+ len
;
1225 tt
->ignore
= ignore
;
1229 gboolean
tvbparse_reset(tvbparse_t
* tt
,
1233 #ifdef TVBPARSE_DEBUG
1234 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_TT
) g_warning("tvbparse_init: offset=%i len=%i",offset
,len
);
1237 len
= (len
== -1) ? (int) tvb_length(tt
->tvb
) : len
;
1239 if( tvb_length_remaining(tt
->tvb
, offset
) >= len
) {
1240 tt
->offset
= offset
;
1241 tt
->end_offset
= offset
+ len
;
1248 guint
tvbparse_curr_offset(tvbparse_t
* tt
) {
1252 static void execute_callbacks(tvbparse_t
* tt
, tvbparse_elem_t
* curr
) {
1253 ep_stack_t stack
= ep_stack_new();
1256 if(curr
->wanted
->before
) {
1257 #ifdef TVBPARSE_DEBUG
1258 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CB
) g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr
->id
,curr
->offset
,curr
->len
);
1260 curr
->wanted
->before(tt
->data
, curr
->wanted
->data
, curr
);
1264 ep_stack_push(stack
,curr
);
1268 #ifdef TVBPARSE_DEBUG
1269 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CB
) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr
->id
,curr
->offset
,curr
->len
);
1271 if(curr
->wanted
->after
) curr
->wanted
->after(tt
->data
, curr
->wanted
->data
, curr
);
1276 while( !curr
&& ep_stack_peek(stack
) ) {
1277 curr
= (tvbparse_elem_t
*)ep_stack_pop(stack
);
1278 #ifdef TVBPARSE_DEBUG
1279 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CB
) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr
->id
,curr
->offset
,curr
->len
);
1281 if( curr
->wanted
->after
) curr
->wanted
->after(tt
->data
, curr
->wanted
->data
, curr
);
1288 gboolean
tvbparse_peek(tvbparse_t
* tt
,
1289 const tvbparse_wanted_t
* wanted
) {
1290 tvbparse_elem_t
* tok
= NULL
;
1292 int offset
= tt
->offset
;
1294 #ifdef TVBPARSE_DEBUG
1295 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_PEEK
) g_warning("tvbparse_peek: ENTER offset=%i",offset
);
1298 offset
+= ignore_fcn(tt
,offset
);
1300 #ifdef TVBPARSE_DEBUG
1301 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_PEEK
) g_warning("tvbparse_peek: after ignore offset=%i",offset
);
1304 consumed
= wanted
->condition(tt
,offset
,wanted
,&tok
);
1306 if (consumed
>= 0) {
1307 #ifdef TVBPARSE_DEBUG
1308 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_PEEK
) g_warning("tvbparse_peek: GOT len=%i",consumed
);
1312 #ifdef TVBPARSE_DEBUG
1313 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_PEEK
) g_warning("tvbparse_peek: NOT GOT");
1320 tvbparse_elem_t
* tvbparse_get(tvbparse_t
* tt
,
1321 const tvbparse_wanted_t
* wanted
) {
1322 tvbparse_elem_t
* tok
= NULL
;
1324 int offset
= tt
->offset
;
1326 #ifdef TVBPARSE_DEBUG
1327 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_GET
) g_warning("tvbparse_get: ENTER offset=%i",offset
);
1330 offset
+= ignore_fcn(tt
,offset
);
1332 #ifdef TVBPARSE_DEBUG
1333 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_GET
) g_warning("tvbparse_get: after ignore offset=%i",offset
);
1336 consumed
= wanted
->condition(tt
,offset
,wanted
,&tok
);
1338 if (consumed
>= 0) {
1339 #ifdef TVBPARSE_DEBUG
1340 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_GET
) g_warning("tvbparse_get: GOT len=%i",consumed
);
1342 execute_callbacks(tt
,tok
);
1343 tt
->offset
= offset
+ consumed
;
1344 #ifdef TVBPARSE_DEBUG
1345 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_GET
) g_warning("tvbparse_get: DONE offset=%i", tt
->offset
);
1355 tvbparse_elem_t
* tvbparse_find(tvbparse_t
* tt
, const tvbparse_wanted_t
* wanted
) {
1356 tvbparse_elem_t
* tok
= NULL
;
1358 int offset
= tt
->offset
;
1359 int target_offset
= offset
-1;
1361 #ifdef TVBPARSE_DEBUG
1362 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_FIND
) g_warning("tvbparse_get: ENTER offset=%i", tt
->offset
);
1366 len
= wanted
->condition(tt
, target_offset
+1, wanted
, &tok
);
1367 } while(len
< 0 && ++target_offset
< tt
->end_offset
);
1370 #ifdef TVBPARSE_DEBUG
1371 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_FIND
) g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset
,len
);
1373 execute_callbacks(tt
,tok
);
1374 tt
->offset
= target_offset
+ len
;
1376 #ifdef TVBPARSE_DEBUG
1377 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_FIND
) g_warning("tvbparse_get: DONE offset=%i", tt
->offset
);
1381 #ifdef TVBPARSE_DEBUG
1382 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_FIND
) g_warning("tvbparse_get: NOT FOUND");
1388 struct _elem_tree_stack_frame
{
1390 tvbparse_elem_t
* elem
;
1393 void tvbparse_tree_add_elem(proto_tree
* tree
, tvbparse_elem_t
* curr
) {
1394 ep_stack_t stack
= ep_stack_new();
1395 struct _elem_tree_stack_frame
* frame
= (struct _elem_tree_stack_frame
*)ep_alloc(sizeof(struct _elem_tree_stack_frame
));
1401 pi
= proto_tree_add_text(frame
->tree
,curr
->tvb
,curr
->offset
,curr
->len
,"%s",tvb_format_text(curr
->tvb
,curr
->offset
,curr
->len
));
1405 ep_stack_push(stack
,frame
);
1406 frame
= (struct _elem_tree_stack_frame
*)ep_alloc(sizeof(struct _elem_tree_stack_frame
));
1407 frame
->tree
= proto_item_add_subtree(pi
,0);
1414 while( !curr
&& ep_stack_peek(stack
) ) {
1415 frame
= (struct _elem_tree_stack_frame
*)ep_stack_pop(stack
);
1416 curr
= frame
->elem
->next
;