3 * Copyright 2005, Luis E. Garcia Ontanon <luis@ontanon.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include <epan/wmem_scopes.h>
19 #include <epan/proto.h>
20 #include <epan/packet_info.h>
21 #include <epan/tvbparse.h>
22 #include <wsutil/ws_assert.h>
25 #define TVBPARSE_DEBUG_ALL 0xffffffff
28 #define TVBPARSE_DEBUG_ 0x80000000
29 #define TVBPARSE_DEBUG_ 0x40000000
30 #define TVBPARSE_DEBUG_ 0x20000000
31 #define TVBPARSE_DEBUG_ 0x10000000
34 #define TVBPARSE_DEBUG_CHAR 0x08000000
35 #define TVBPARSE_DEBUG_CHARS 0x04000000
36 #define TVBPARSE_DEBUG_NOT_CHAR 0x02000000
37 #define TVBPARSE_DEBUG_NOT_CHARS 0x01000000
38 #define TVBPARSE_DEBUG_STRING 0x00800000
39 #define TVBPARSE_DEBUG_CASESTRING 0x00400000
40 #define TVBPARSE_DEBUG_ONEOF 0x00200000
41 #define TVBPARSE_DEBUG_HASH 0x00100000
42 #define TVBPARSE_DEBUG_SEQ 0x00080000
43 #define TVBPARSE_DEBUG_SOME 0x00040000
44 #define TVBPARSE_DEBUG_UNTIL 0x00020000
46 #define TVBPARSE_DEBUG_ 0x00010000
47 #define TVBPARSE_DEBUG_ 0x00008000
48 #define TVBPARSE_DEBUG_ 0x00004000
49 #define TVBPARSE_DEBUG_ 0x00002000
50 #define TVBPARSE_DEBUG_ 0x00001000
52 #define TVBPARSE_DEBUG_TT 0x00000800
53 #define TVBPARSE_DEBUG_CB 0x00000400
54 #define TVBPARSE_DEBUG_GET 0x00000200
55 #define TVBPARSE_DEBUG_FIND 0x00000100
56 #define TVBPARSE_DEBUG_NEWTOK 0x00000080
57 #define TVBPARSE_DEBUG_IGNORE 0x00000040
58 #define TVBPARSE_DEBUG_PEEK 0x00000020
60 #define TVBPARSE_DEBUG_ 0x00000010
61 #define TVBPARSE_DEBUG_ 0x00000008
62 #define TVBPARSE_DEBUG_ 0x00000004
63 #define TVBPARSE_DEBUG_ 0x00000002
64 #define TVBPARSE_DEBUG_ 0x00000001
68 #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
71 #define TVBPARSE_MAX_RECURSION_DEPTH 100 // Arbitrary. Matches DAAP and PNIO.
73 static tvbparse_elem_t
* new_tok(tvbparse_t
* tt
,
77 const tvbparse_wanted_t
* wanted
) {
81 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_NEWTOK
) ws_warning("new_tok: id=%i offset=%u len=%u",id
,offset
,len
);
84 tok
= wmem_new(tt
->scope
, tvbparse_elem_t
);
100 static int ignore_fcn(tvbparse_t
* tt
, int offset
) {
103 tvbparse_elem_t
* ignored
= NULL
;
105 if (!tt
->ignore
) return 0;
107 #ifdef TVBPARSE_DEBUG
108 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_IGNORE
) ws_warning("ignore: enter");
111 while ((consumed
= tt
->ignore
->condition(tt
,offset
,tt
->ignore
,&ignored
)) > 0) {
114 #ifdef TVBPARSE_DEBUG
115 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_IGNORE
) ws_warning("ignore: consumed=%i",consumed
);
120 #ifdef TVBPARSE_DEBUG
121 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_IGNORE
) ws_warning("ignore: len=%i",len
);
128 static int cond_char (tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
132 #ifdef TVBPARSE_DEBUG
133 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CHAR
) ws_warning("cond_char: control='%s'",wanted
->control
.str
);
136 if ( offset
+ 1 > tt
->end_offset
)
139 t
= (char) tvb_get_uint8(tt
->tvb
,offset
);
141 for(i
= 0; (c
= wanted
->control
.str
[i
]) && offset
<= tt
->end_offset
; i
++) {
143 *tok
= new_tok(tt
,wanted
->id
,offset
,1,wanted
);
144 #ifdef TVBPARSE_DEBUG
145 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CHAR
) ws_warning("cond_char: GOT: '%c'",c
);
154 tvbparse_wanted_t
* tvbparse_char(const int id
,
157 tvbparse_action_t before_cb
,
158 tvbparse_action_t after_cb
) {
159 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
161 w
->condition
= cond_char
;
163 w
->control
.str
= chr
;
166 w
->before
= before_cb
;
172 static int cond_chars_common(tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
175 int left
= tt
->end_offset
- offset
;
177 #ifdef TVBPARSE_DEBUG
178 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CHARS
) ws_warning("cond_chars_common: control='%s'",wanted
->control
.str
);
181 if ( offset
+ (int)wanted
->min
> tt
->end_offset
)
184 left
= left
< (int) wanted
->max
? left
: (int) wanted
->max
;
187 uint8_t t
= tvb_get_uint8(tt
->tvb
,offset
++);
189 if (!wanted
->control
.str
[t
])
196 if (length
< wanted
->min
) {
199 *tok
= new_tok(tt
,wanted
->id
,start
,length
,wanted
);
200 #ifdef TVBPARSE_DEBUG
201 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CHARS
) ws_warning("cond_chars_common: GOT len=%i",length
);
207 tvbparse_wanted_t
* tvbparse_chars(const int id
,
208 const unsigned min_len
,
209 const unsigned max_len
,
212 tvbparse_action_t before_cb
,
213 tvbparse_action_t after_cb
)
215 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
219 accept_str
= (char *)wmem_alloc(wmem_epan_scope(), 256);
220 memset(accept_str
, 0x00, 256);
221 for (i
= 0; chr
[i
]; i
++)
222 accept_str
[(unsigned)chr
[i
]] = (char)0xFF;
224 w
->condition
= cond_chars_common
;
226 w
->control
.str
= accept_str
;
227 w
->min
= min_len
? min_len
: 1;
228 w
->max
= max_len
? max_len
: INT_MAX
/2;
230 w
->before
= before_cb
;
237 static int cond_not_char(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
240 bool not_matched
= false;
242 #ifdef TVBPARSE_DEBUG
243 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_NOT_CHAR
) ws_warning("cond_not_char: control='%s'",wanted
->control
.str
);
246 if ( offset
>= tt
->end_offset
) {
250 t
= (char) tvb_get_uint8(tt
->tvb
,offset
);
252 for(i
= 0; (c
= wanted
->control
.str
[i
]); i
++) {
261 *tok
= new_tok(tt
,wanted
->id
,offset
,1,wanted
);
262 #ifdef TVBPARSE_DEBUG
263 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_NOT_CHAR
) ws_warning("cond_not_char: GOT='%c'",t
);
269 tvbparse_wanted_t
* tvbparse_not_char(const int id
,
272 tvbparse_action_t before_cb
,
273 tvbparse_action_t after_cb
) {
274 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
276 w
->condition
= cond_not_char
;
278 w
->control
.str
= chr
;
280 w
->before
= before_cb
;
286 tvbparse_wanted_t
* tvbparse_not_chars(const int id
,
287 const unsigned min_len
,
288 const unsigned max_len
,
291 tvbparse_action_t before_cb
,
292 tvbparse_action_t after_cb
)
294 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
298 /* cond_chars_common() use accept string, so mark all elements with, and later unset from reject */
299 accept_str
= (char *)wmem_alloc(wmem_epan_scope(), 256);
300 memset(accept_str
, 0xFF, 256);
301 for (i
= 0; chr
[i
]; i
++)
302 accept_str
[(unsigned) chr
[i
]] = '\0';
304 w
->condition
= cond_chars_common
;
306 w
->control
.str
= accept_str
;
308 w
->min
= min_len
? min_len
: 1;
309 w
->max
= max_len
? max_len
: INT_MAX
/2;
311 w
->before
= before_cb
;
318 static int cond_string(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
319 int len
= wanted
->len
;
320 #ifdef TVBPARSE_DEBUG
321 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_STRING
) ws_warning("cond_string: control='%s'",wanted
->control
.str
);
324 if ( offset
+ wanted
->len
> tt
->end_offset
)
327 if ( tvb_strneql(tt
->tvb
, offset
, wanted
->control
.str
, len
) == 0 ) {
328 *tok
= new_tok(tt
,wanted
->id
,offset
,len
,wanted
);
329 #ifdef TVBPARSE_DEBUG
330 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_STRING
) ws_warning("cond_string: GOT len=%i",len
);
338 tvbparse_wanted_t
* tvbparse_string(const int id
,
341 tvbparse_action_t before_cb
,
342 tvbparse_action_t after_cb
) {
343 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
345 w
->condition
= cond_string
;
347 w
->control
.str
= str
;
348 w
->len
= (int) strlen(str
);
350 w
->before
= before_cb
;
356 static int cond_casestring(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
357 int len
= wanted
->len
;
358 #ifdef TVBPARSE_DEBUG
359 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CASESTRING
) ws_warning("cond_casestring: control='%s'",wanted
->control
.str
);
362 if ( offset
+ len
> tt
->end_offset
)
365 if ( tvb_strncaseeql(tt
->tvb
, offset
, wanted
->control
.str
, len
) == 0 ) {
366 *tok
= new_tok(tt
,wanted
->id
,offset
,len
,wanted
);
367 #ifdef TVBPARSE_DEBUG
368 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CASESTRING
) ws_warning("cond_casestring: GOT len=%i",len
);
377 tvbparse_wanted_t
* tvbparse_casestring(const int id
,
380 tvbparse_action_t before_cb
,
381 tvbparse_action_t after_cb
) {
382 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
384 w
->condition
= cond_casestring
;
386 w
->control
.str
= str
;
387 w
->len
= (int) strlen(str
);
389 w
->before
= before_cb
;
395 static int cond_one_of(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
397 #ifdef TVBPARSE_DEBUG
398 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_ONEOF
) ws_warning("cond_one_of: START");
401 if ( offset
> tt
->end_offset
)
404 if (++tt
->recursion_depth
> TVBPARSE_MAX_RECURSION_DEPTH
)
407 for(i
=0; i
< wanted
->control
.elems
->len
; i
++) {
408 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_ptr_array_index(wanted
->control
.elems
,i
);
409 tvbparse_elem_t
* new_elem
= NULL
;
412 if ( offset
+ w
->len
> tt
->end_offset
)
415 curr_len
= w
->condition(tt
, offset
, w
, &new_elem
);
418 *tok
= new_tok(tt
, wanted
->id
, new_elem
->offset
, new_elem
->len
, wanted
);
419 (*tok
)->sub
= new_elem
;
420 #ifdef TVBPARSE_DEBUG
421 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_ONEOF
) ws_warning("cond_one_of: GOT len=%i",curr_len
);
423 tt
->recursion_depth
--;
428 tt
->recursion_depth
--;
433 tvbparse_wanted_cleanup_cb(wmem_allocator_t
* allocator _U_
, wmem_cb_event_t event _U_
, void *user_data
)
435 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)user_data
;
436 g_ptr_array_free(w
->control
.elems
, true);
440 tvbparse_wanted_t
* tvbparse_set_oneof(const int id
,
442 tvbparse_action_t before_cb
,
443 tvbparse_action_t after_cb
,
445 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
449 w
->condition
= cond_one_of
;
452 w
->before
= before_cb
;
454 w
->control
.elems
= g_ptr_array_new();
455 wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb
, w
);
457 va_start(ap
,after_cb
);
459 while(( el
= va_arg(ap
,tvbparse_t
*) )) {
460 g_ptr_array_add(w
->control
.elems
,el
);
468 static int cond_hash(tvbparse_t
* tt
, const int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
471 tvbparse_elem_t
* key_elem
= NULL
;
472 tvbparse_wanted_t
* value_wanted
= NULL
;
474 tvbparse_elem_t
* value_elem
= NULL
;
476 tvbparse_elem_t
* ret_tok
;
478 #ifdef TVBPARSE_DEBUG
479 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_HASH
) ws_warning("cond_hash: START");
482 if ( offset
> tt
->end_offset
)
485 if (++tt
->recursion_depth
> TVBPARSE_MAX_RECURSION_DEPTH
)
488 key_len
= wanted
->control
.hash
.key
->condition(tt
, offset
, wanted
->control
.hash
.key
, &key_elem
);
491 tt
->recursion_depth
--;
495 key
= tvb_get_string_enc(tt
->scope
,key_elem
->parser
->tvb
,key_elem
->offset
,key_elem
->len
, ENC_ASCII
);
496 #ifdef TVBPARSE_DEBUG
497 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_HASH
) ws_warning("cond_hash: got key='%s'",key
);
500 if ((value_wanted
= (tvbparse_wanted_t
*)wmem_map_lookup(wanted
->control
.hash
.table
,key
))) {
501 value_len
= value_wanted
->condition(tt
, offset
+ key_len
, value_wanted
, &value_elem
);
502 } else if (wanted
->control
.hash
.other
) {
503 value_len
= wanted
->control
.hash
.other
->condition(tt
, offset
+key_len
, wanted
->control
.hash
.other
, &value_elem
);
505 tt
->recursion_depth
--;
509 tt
->recursion_depth
--;
513 tt
->recursion_depth
--;
515 tot_len
= key_len
+ value_len
;
517 ret_tok
= new_tok(tt
, value_elem
->id
, offset
, tot_len
, wanted
);
518 ret_tok
->sub
= key_elem
;
519 ret_tok
->sub
->last
->next
= value_elem
;
522 #ifdef TVBPARSE_DEBUG
523 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_HASH
) ws_warning("cond_hash: GOT len=%i",tot_len
);
529 tvbparse_wanted_t
* tvbparse_hashed(const int id
,
531 tvbparse_action_t before_cb
,
532 tvbparse_action_t after_cb
,
533 tvbparse_wanted_t
* key
,
534 tvbparse_wanted_t
* other
,
536 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
538 tvbparse_wanted_t
* el
;
541 w
->condition
= cond_hash
;
544 w
->before
= before_cb
;
546 w
->control
.hash
.table
= wmem_map_new(wmem_epan_scope(), g_str_hash
,g_str_equal
);
547 w
->control
.hash
.key
= key
;
548 w
->control
.hash
.other
= other
;
552 while(( name
= va_arg(ap
,char*) )) {
553 el
= va_arg(ap
,tvbparse_wanted_t
*);
554 wmem_map_insert(w
->control
.hash
.table
,name
,el
);
562 void tvbparse_hashed_add(tvbparse_wanted_t
* w
, ...) {
563 tvbparse_wanted_t
* el
;
569 while (( name
= va_arg(ap
,char*) )) {
570 el
= va_arg(ap
,tvbparse_wanted_t
*);
571 wmem_map_insert(w
->control
.hash
.table
,name
,el
);
577 static int cond_seq(tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
581 tvbparse_elem_t
* ret_tok
= NULL
;
583 #ifdef TVBPARSE_DEBUG
584 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SEQ
) ws_warning("cond_seq: START");
587 if ( offset
> tt
->end_offset
)
590 if (++tt
->recursion_depth
> TVBPARSE_MAX_RECURSION_DEPTH
)
593 for(i
=0; i
< wanted
->control
.elems
->len
; i
++) {
594 tvbparse_wanted_t
* w
= (tvbparse_wanted_t
*)g_ptr_array_index(wanted
->control
.elems
,i
);
595 tvbparse_elem_t
* new_elem
= NULL
;
597 if ( offset
+ w
->len
> tt
->end_offset
) {
598 tt
->recursion_depth
--;
602 len
= w
->condition(tt
, offset
, w
, &new_elem
);
607 ret_tok
->len
= (new_elem
->offset
- ret_tok
->offset
) + new_elem
->len
;
608 ret_tok
->sub
->last
->next
= new_elem
;
609 ret_tok
->sub
->last
= new_elem
;
611 ret_tok
= new_tok(tt
, wanted
->id
, new_elem
->offset
, new_elem
->len
, wanted
);
612 ret_tok
->sub
= new_elem
;
613 new_elem
->last
= new_elem
;
616 tt
->recursion_depth
--;
621 offset
+= ignore_fcn(tt
,offset
);
624 tt
->recursion_depth
--;
628 #ifdef TVBPARSE_DEBUG
629 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SEQ
) ws_warning("cond_seq: GOT len=%i",offset
- start
);
632 return offset
- start
;
636 tvbparse_wanted_t
* tvbparse_set_seq(const int id
,
638 tvbparse_action_t before_cb
,
639 tvbparse_action_t after_cb
,
641 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
642 tvbparse_wanted_t
* el
= NULL
;
645 w
->condition
= cond_seq
;
648 w
->before
= before_cb
;
650 w
->control
.elems
= g_ptr_array_new();
651 wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb
, w
);
653 va_start(ap
,after_cb
);
655 while(( el
= va_arg(ap
,tvbparse_wanted_t
*) )) {
656 g_ptr_array_add(w
->control
.elems
,el
);
663 static int cond_some(tvbparse_t
* tt
, int offset
, const tvbparse_wanted_t
* wanted
, tvbparse_elem_t
** tok
) {
664 unsigned got_so_far
= 0;
666 tvbparse_elem_t
* ret_tok
= NULL
;
667 #ifdef TVBPARSE_DEBUG
668 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SOME
) ws_warning("cond_some: START");
671 if ( offset
> tt
->end_offset
)
674 if (++tt
->recursion_depth
> TVBPARSE_MAX_RECURSION_DEPTH
)
677 if ( wanted
->min
== 0 ) {
678 ret_tok
= new_tok(tt
,wanted
->id
,offset
,0,wanted
);
681 while (got_so_far
< wanted
->max
) {
682 tvbparse_elem_t
* new_elem
= NULL
;
685 if ( offset
> tt
->end_offset
) {
686 tt
->recursion_depth
--;
690 consumed
= wanted
->control
.subelem
->condition(tt
, offset
, wanted
->control
.subelem
, &new_elem
);
695 ret_tok
->len
= (new_elem
->offset
- ret_tok
->offset
) + new_elem
->len
;
698 ret_tok
->sub
->last
->next
= new_elem
;
699 ret_tok
->sub
->last
= new_elem
;
701 ret_tok
->sub
= new_elem
;
704 ret_tok
= new_tok(tt
, wanted
->id
, new_elem
->offset
, new_elem
->len
, wanted
);
705 ret_tok
->sub
= new_elem
;
715 tt
->recursion_depth
--;
717 #ifdef TVBPARSE_DEBUG
718 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_SOME
) ws_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
) ws_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
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
742 ws_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
) ws_warning("cond_until: START");
765 if ( offset
+ wanted
->control
.until
.subelem
->len
> tt
->end_offset
)
768 if (++tt
->recursion_depth
> TVBPARSE_MAX_RECURSION_DEPTH
)
772 len
= wanted
->control
.until
.subelem
->condition(tt
, target_offset
++, wanted
->control
.until
.subelem
, &new_elem
);
773 } while(len
< 0 && target_offset
+1 < tt
->end_offset
);
775 tt
->recursion_depth
--;
779 new_elem
->id
= wanted
->id
;
780 new_elem
->next
= NULL
;
781 new_elem
->last
= NULL
;
782 new_elem
->wanted
= wanted
;
783 new_elem
->offset
= offset
;
787 switch (wanted
->control
.until
.mode
) {
788 case TP_UNTIL_INCLUDE
:
789 new_elem
->len
= target_offset
- offset
- 1 + len
;
790 #ifdef TVBPARSE_DEBUG
791 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_UNTIL
) ws_warning("cond_until: GOT len=%i",target_offset
- offset
-1 + len
);
793 return target_offset
- offset
-1 + len
;
795 new_elem
->len
= target_offset
- offset
- 1;
796 #ifdef TVBPARSE_DEBUG
797 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_UNTIL
) ws_warning("cond_until: GOT len=%i",target_offset
- offset
-1 + len
);
799 return target_offset
- offset
- 1 + len
;
801 new_elem
->len
= target_offset
- offset
- 1;
802 #ifdef TVBPARSE_DEBUG
803 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_UNTIL
) ws_warning("cond_until: GOT len=%i",target_offset
- offset
-1);
805 return target_offset
- offset
-1;
807 DISSECTOR_ASSERT_NOT_REACHED();
816 tvbparse_wanted_t
* tvbparse_until(const int id
,
818 tvbparse_action_t before_cb
,
819 tvbparse_action_t after_cb
,
820 const tvbparse_wanted_t
* el
,
821 until_mode_t until_mode
) {
822 tvbparse_wanted_t
* w
= wmem_new0(wmem_epan_scope(), tvbparse_wanted_t
);
824 w
->condition
= cond_until
;
825 w
->control
.until
.mode
= until_mode
;
826 w
->control
.until
.subelem
= el
;
829 w
->before
= before_cb
;
835 tvbparse_wanted_t
* tvbparse_quoted(const int id
,
837 tvbparse_action_t before_cb
,
838 tvbparse_action_t after_cb
,
842 char* esc_quot
= wmem_strdup_printf(wmem_epan_scope(), "%c%c",esc
,quote
);
843 char* quot
= wmem_strdup_printf(wmem_epan_scope(), "%c",quote
);
844 tvbparse_wanted_t
* want_quot
= tvbparse_char(-1,quot
,NULL
,NULL
,NULL
);
846 return tvbparse_set_oneof(id
, data
, before_cb
, after_cb
,
847 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
849 tvbparse_set_seq(-1,NULL
,NULL
,NULL
,
850 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
851 tvbparse_string(-1,esc_quot
,NULL
,NULL
,NULL
),
852 tvbparse_not_chars(-1,0,0,quot
,NULL
,NULL
,NULL
),
857 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
864 void tvbparse_shrink_token_cb(void* tvbparse_data _U_
,
865 const void* wanted_data _U_
,
866 tvbparse_elem_t
* tok
) {
871 tvbparse_t
* tvbparse_init(wmem_allocator_t
*scope
,
876 const tvbparse_wanted_t
* ignore
) {
877 tvbparse_t
* tt
= wmem_new(scope
, tvbparse_t
);
879 #ifdef TVBPARSE_DEBUG
880 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_TT
) ws_warning("tvbparse_init: offset=%i len=%i",offset
,len
);
886 len
= (len
== -1) ? (int) tvb_captured_length(tvb
) : len
;
887 tt
->end_offset
= offset
+ len
;
890 tt
->recursion_depth
= 0;
894 bool tvbparse_reset(tvbparse_t
* tt
,
898 #ifdef TVBPARSE_DEBUG
899 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_TT
) ws_warning("tvbparse_init: offset=%i len=%i",offset
,len
);
902 len
= (len
== -1) ? (int) tvb_captured_length(tt
->tvb
) : len
;
904 if( tvb_captured_length_remaining(tt
->tvb
, offset
) >= len
) {
906 tt
->end_offset
= offset
+ len
;
913 unsigned tvbparse_curr_offset(tvbparse_t
* tt
) {
917 static void execute_callbacks(tvbparse_t
* tt
, tvbparse_elem_t
* curr
) {
918 wmem_stack_t
*stack
= wmem_stack_new(tt
->scope
);
921 if(curr
->wanted
->before
) {
922 #ifdef TVBPARSE_DEBUG
923 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CB
) ws_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr
->id
,curr
->offset
,curr
->len
);
925 curr
->wanted
->before(tt
->data
, curr
->wanted
->data
, curr
);
929 wmem_stack_push(stack
, curr
);
933 #ifdef TVBPARSE_DEBUG
934 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CB
) ws_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr
->id
,curr
->offset
,curr
->len
);
936 if(curr
->wanted
->after
) curr
->wanted
->after(tt
->data
, curr
->wanted
->data
, curr
);
941 while( !curr
&& wmem_stack_count(stack
) > 0 ) {
942 curr
= (tvbparse_elem_t
*)wmem_stack_pop(stack
);
943 #ifdef TVBPARSE_DEBUG
944 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_CB
) ws_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr
->id
,curr
->offset
,curr
->len
);
946 if( curr
->wanted
->after
) curr
->wanted
->after(tt
->data
, curr
->wanted
->data
, curr
);
953 bool tvbparse_peek(tvbparse_t
* tt
,
954 const tvbparse_wanted_t
* wanted
) {
955 tvbparse_elem_t
* tok
= NULL
;
957 int offset
= tt
->offset
;
959 #ifdef TVBPARSE_DEBUG
960 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_PEEK
) ws_warning("tvbparse_peek: ENTER offset=%i",offset
);
963 offset
+= ignore_fcn(tt
,offset
);
965 #ifdef TVBPARSE_DEBUG
966 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_PEEK
) ws_warning("tvbparse_peek: after ignore offset=%i",offset
);
969 consumed
= wanted
->condition(tt
,offset
,wanted
,&tok
);
972 #ifdef TVBPARSE_DEBUG
973 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_PEEK
) ws_warning("tvbparse_peek: GOT len=%i",consumed
);
977 #ifdef TVBPARSE_DEBUG
978 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_PEEK
) ws_warning("tvbparse_peek: NOT GOT");
985 tvbparse_elem_t
* tvbparse_get(tvbparse_t
* tt
,
986 const tvbparse_wanted_t
* wanted
) {
987 tvbparse_elem_t
* tok
= NULL
;
989 int offset
= tt
->offset
;
991 #ifdef TVBPARSE_DEBUG
992 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_GET
) ws_warning("tvbparse_get: ENTER offset=%i",offset
);
995 offset
+= ignore_fcn(tt
,offset
);
997 #ifdef TVBPARSE_DEBUG
998 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_GET
) ws_warning("tvbparse_get: after ignore offset=%i",offset
);
1001 consumed
= wanted
->condition(tt
,offset
,wanted
,&tok
);
1003 if (consumed
>= 0) {
1004 #ifdef TVBPARSE_DEBUG
1005 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_GET
) ws_warning("tvbparse_get: GOT len=%i",consumed
);
1007 execute_callbacks(tt
,tok
);
1008 tt
->offset
= offset
+ consumed
;
1009 #ifdef TVBPARSE_DEBUG
1010 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_GET
) ws_warning("tvbparse_get: DONE offset=%i", tt
->offset
);
1020 tvbparse_elem_t
* tvbparse_find(tvbparse_t
* tt
, const tvbparse_wanted_t
* wanted
) {
1021 tvbparse_elem_t
* tok
= NULL
;
1023 int offset
= tt
->offset
;
1024 int target_offset
= offset
-1;
1026 #ifdef TVBPARSE_DEBUG
1027 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_FIND
) ws_warning("tvbparse_get: ENTER offset=%i", tt
->offset
);
1031 len
= wanted
->condition(tt
, target_offset
+1, wanted
, &tok
);
1032 } while(len
< 0 && ++target_offset
< tt
->end_offset
);
1035 #ifdef TVBPARSE_DEBUG
1036 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_FIND
) ws_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset
,len
);
1038 execute_callbacks(tt
,tok
);
1039 tt
->offset
= target_offset
+ len
;
1041 #ifdef TVBPARSE_DEBUG
1042 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_FIND
) ws_warning("tvbparse_get: DONE offset=%i", tt
->offset
);
1046 #ifdef TVBPARSE_DEBUG
1047 if (TVBPARSE_DEBUG
& TVBPARSE_DEBUG_FIND
) ws_warning("tvbparse_get: NOT FOUND");
1053 struct _elem_tree_stack_frame
{
1055 tvbparse_elem_t
* elem
;
1058 void tvbparse_tree_add_elem(proto_tree
* tree
, tvbparse_elem_t
* curr
) {
1059 wmem_stack_t
*stack
= wmem_stack_new(curr
->parser
->scope
);
1060 struct _elem_tree_stack_frame
* frame
= wmem_new(curr
->parser
->scope
, struct _elem_tree_stack_frame
);
1066 pi
= proto_tree_add_format_text(frame
->tree
,curr
->parser
->tvb
,curr
->offset
,curr
->len
);
1070 wmem_stack_push(stack
, frame
);
1071 frame
= wmem_new(curr
->parser
->scope
, struct _elem_tree_stack_frame
);
1072 frame
->tree
= proto_item_add_subtree(pi
,0);
1079 while( !curr
&& wmem_stack_count(stack
) > 0 ) {
1080 frame
= (struct _elem_tree_stack_frame
*)wmem_stack_pop(stack
);
1081 curr
= frame
->elem
->next
;
1088 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1093 * indent-tabs-mode: nil
1096 * vi: set shiftwidth=4 tabstop=8 expandtab:
1097 * :indentSize=4:tabSize=8:noTabs=true: