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/wmem.h>
19 #include <epan/proto.h>
20 #include <epan/packet_info.h>
21 #include <epan/tvbparse.h>
24 #define TVBPARSE_DEBUG_ALL 0xffffffff
27 #define TVBPARSE_DEBUG_ 0x80000000
28 #define TVBPARSE_DEBUG_ 0x40000000
29 #define TVBPARSE_DEBUG_ 0x20000000
30 #define TVBPARSE_DEBUG_ 0x10000000
33 #define TVBPARSE_DEBUG_CHAR 0x08000000
34 #define TVBPARSE_DEBUG_CHARS 0x04000000
35 #define TVBPARSE_DEBUG_NOT_CHAR 0x02000000
36 #define TVBPARSE_DEBUG_NOT_CHARS 0x01000000
37 #define TVBPARSE_DEBUG_STRING 0x00800000
38 #define TVBPARSE_DEBUG_CASESTRING 0x00400000
39 #define TVBPARSE_DEBUG_ONEOF 0x00200000
40 #define TVBPARSE_DEBUG_HASH 0x00100000
41 #define TVBPARSE_DEBUG_SEQ 0x00080000
42 #define TVBPARSE_DEBUG_SOME 0x00040000
43 #define TVBPARSE_DEBUG_UNTIL 0x00020000
45 #define TVBPARSE_DEBUG_ 0x00010000
46 #define TVBPARSE_DEBUG_ 0x00008000
47 #define TVBPARSE_DEBUG_ 0x00004000
48 #define TVBPARSE_DEBUG_ 0x00002000
49 #define TVBPARSE_DEBUG_ 0x00001000
51 #define TVBPARSE_DEBUG_TT 0x00000800
52 #define TVBPARSE_DEBUG_CB 0x00000400
53 #define TVBPARSE_DEBUG_GET 0x00000200
54 #define TVBPARSE_DEBUG_FIND 0x00000100
55 #define TVBPARSE_DEBUG_NEWTOK 0x00000080
56 #define TVBPARSE_DEBUG_IGNORE 0x00000040
57 #define TVBPARSE_DEBUG_PEEK 0x00000020
59 #define TVBPARSE_DEBUG_ 0x00000010
60 #define TVBPARSE_DEBUG_ 0x00000008
61 #define TVBPARSE_DEBUG_ 0x00000004
62 #define TVBPARSE_DEBUG_ 0x00000002
63 #define TVBPARSE_DEBUG_ 0x00000001
67 #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
70 #define TVBPARSE_MAX_RECURSION_DEPTH 100 // Arbitrary. Matches DAAP and PNIO.
72 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
76 const tvbparse_wanted_t* wanted) {
80 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) g_warning("new_tok: id=%i offset=%u len=%u",id,offset,len);
83 tok = wmem_new(wmem_packet_scope(), tvbparse_elem_t);
98 static int ignore_fcn(tvbparse_t* tt, int offset) {
101 tvbparse_elem_t* ignored = NULL;
103 if (!tt->ignore) return 0;
105 #ifdef TVBPARSE_DEBUG
106 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: enter");
109 while ((consumed = tt->ignore->condition(tt,offset,tt->ignore,&ignored)) > 0) {
112 #ifdef TVBPARSE_DEBUG
113 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: consumed=%i",consumed);
118 #ifdef TVBPARSE_DEBUG
119 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: len=%i",len);
126 static int cond_char (tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
130 #ifdef TVBPARSE_DEBUG
131 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: control='%s'",wanted->control.str);
134 if ( offset + 1 > tt->end_offset )
137 t = (gchar) tvb_get_guint8(tt->tvb,offset);
139 for(i = 0; (c = wanted->control.str[i]) && offset <= tt->end_offset; i++) {
141 *tok = new_tok(tt,wanted->id,offset,1,wanted);
142 #ifdef TVBPARSE_DEBUG
143 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: GOT: '%c'",c);
152 tvbparse_wanted_t* tvbparse_char(const int id,
155 tvbparse_action_t before_cb,
156 tvbparse_action_t after_cb) {
157 tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t);
159 w->condition = cond_char;
161 w->control.str = chr;
164 w->before = before_cb;
170 static int cond_chars_common(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
173 int left = tt->end_offset - offset;
175 #ifdef TVBPARSE_DEBUG
176 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars_common: control='%s'",wanted->control.str);
179 if ( offset + (int)wanted->min > tt->end_offset )
182 left = left < (int) wanted->max ? left : (int) wanted->max;
185 guint8 t = tvb_get_guint8(tt->tvb,offset++);
187 if (!wanted->control.str[t])
194 if (length < wanted->min) {
197 *tok = new_tok(tt,wanted->id,start,length,wanted);
198 #ifdef TVBPARSE_DEBUG
199 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars_common: GOT len=%i",length);
205 tvbparse_wanted_t* tvbparse_chars(const int id,
210 tvbparse_action_t before_cb,
211 tvbparse_action_t after_cb)
213 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
217 accept_str = (char *)wmem_alloc(wmem_epan_scope(), 256);
218 memset(accept_str, 0x00, 256);
219 for (i = 0; chr[i]; i++)
220 accept_str[(unsigned)chr[i]] = (char)0xFF;
222 w->condition = cond_chars_common;
224 w->control.str = accept_str;
225 w->min = min_len ? min_len : 1;
226 w->max = max_len ? max_len : G_MAXINT/2;
228 w->before = before_cb;
235 static int cond_not_char(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
238 gboolean not_matched = FALSE;
240 #ifdef TVBPARSE_DEBUG
241 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: control='%s'",wanted->control.str);
244 if ( offset >= tt->end_offset ) {
248 t = (gchar) tvb_get_guint8(tt->tvb,offset);
250 for(i = 0; (c = wanted->control.str[i]); i++) {
259 *tok = new_tok(tt,wanted->id,offset,1,wanted);
260 #ifdef TVBPARSE_DEBUG
261 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: GOT='%c'",t);
267 tvbparse_wanted_t* tvbparse_not_char(const int id,
270 tvbparse_action_t before_cb,
271 tvbparse_action_t after_cb) {
272 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
274 w->condition = cond_not_char;
276 w->control.str = chr;
278 w->before = before_cb;
284 tvbparse_wanted_t* tvbparse_not_chars(const int id,
289 tvbparse_action_t before_cb,
290 tvbparse_action_t after_cb)
292 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
296 /* cond_chars_common() use accept string, so mark all elements with, and later unset from reject */
297 accept_str = (char *)wmem_alloc(wmem_epan_scope(), 256);
298 memset(accept_str, 0xFF, 256);
299 for (i = 0; chr[i]; i++)
300 accept_str[(unsigned) chr[i]] = '\0';
302 w->condition = cond_chars_common;
304 w->control.str = accept_str;
306 w->min = min_len ? min_len : 1;
307 w->max = max_len ? max_len : G_MAXINT/2;
309 w->before = before_cb;
316 static int cond_string(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
317 int len = wanted->len;
318 #ifdef TVBPARSE_DEBUG
319 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: control='%s'",wanted->control.str);
322 if ( offset + wanted->len > tt->end_offset )
325 if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
326 *tok = new_tok(tt,wanted->id,offset,len,wanted);
327 #ifdef TVBPARSE_DEBUG
328 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: GOT len=%i",len);
336 tvbparse_wanted_t* tvbparse_string(const int id,
339 tvbparse_action_t before_cb,
340 tvbparse_action_t after_cb) {
341 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
343 w->condition = cond_string;
345 w->control.str = str;
346 w->len = (int) strlen(str);
348 w->before = before_cb;
354 static int cond_casestring(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
355 int len = wanted->len;
356 #ifdef TVBPARSE_DEBUG
357 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: control='%s'",wanted->control.str);
360 if ( offset + len > tt->end_offset )
363 if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
364 *tok = new_tok(tt,wanted->id,offset,len,wanted);
365 #ifdef TVBPARSE_DEBUG
366 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: GOT len=%i",len);
375 tvbparse_wanted_t* tvbparse_casestring(const int id,
378 tvbparse_action_t before_cb,
379 tvbparse_action_t after_cb) {
380 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
382 w->condition = cond_casestring;
384 w->control.str = str;
385 w->len = (int) strlen(str);
387 w->before = before_cb;
393 static int cond_one_of(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
395 #ifdef TVBPARSE_DEBUG
396 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: START");
399 if ( offset > tt->end_offset )
402 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
405 for(i=0; i < wanted->control.elems->len; i++) {
406 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i);
407 tvbparse_elem_t* new_elem = NULL;
410 if ( offset + w->len > tt->end_offset )
413 curr_len = w->condition(tt, offset, w, &new_elem);
416 *tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
417 (*tok)->sub = new_elem;
418 #ifdef TVBPARSE_DEBUG
419 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: GOT len=%i",curr_len);
421 tt->recursion_depth--;
426 tt->recursion_depth--;
431 tvbparse_wanted_cleanup_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data)
433 tvbparse_wanted_t* w = (tvbparse_wanted_t *)user_data;
434 g_ptr_array_free(w->control.elems, TRUE);
438 tvbparse_wanted_t* tvbparse_set_oneof(const int id,
440 tvbparse_action_t before_cb,
441 tvbparse_action_t after_cb,
443 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
447 w->condition = cond_one_of;
450 w->before = before_cb;
452 w->control.elems = g_ptr_array_new();
453 wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb, w);
455 va_start(ap,after_cb);
457 while(( el = va_arg(ap,tvbparse_t*) )) {
458 g_ptr_array_add(w->control.elems,el);
466 static int cond_hash(tvbparse_t* tt, const int offset, const tvbparse_wanted_t* wanted, tvbparse_elem_t** tok) {
469 tvbparse_elem_t* key_elem = NULL;
470 tvbparse_wanted_t* value_wanted = NULL;
472 tvbparse_elem_t* value_elem = NULL;
474 tvbparse_elem_t* ret_tok;
476 #ifdef TVBPARSE_DEBUG
477 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: START");
480 if ( offset > tt->end_offset )
483 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
486 key_len = wanted->control.hash.key->condition(tt, offset, wanted->control.hash.key, &key_elem);
489 tt->recursion_depth--;
493 key = tvb_get_string_enc(wmem_packet_scope(),key_elem->tvb,key_elem->offset,key_elem->len, ENC_ASCII);
494 #ifdef TVBPARSE_DEBUG
495 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: got key='%s'",key);
498 if ((value_wanted = (tvbparse_wanted_t *)wmem_map_lookup(wanted->control.hash.table,key))) {
499 value_len = value_wanted->condition(tt, offset + key_len, value_wanted, &value_elem);
500 } else if (wanted->control.hash.other) {
501 value_len = wanted->control.hash.other->condition(tt, offset+key_len, wanted->control.hash.other, &value_elem);
503 tt->recursion_depth--;
507 tt->recursion_depth--;
511 tt->recursion_depth--;
513 tot_len = key_len + value_len;
515 ret_tok = new_tok(tt, value_elem->id, offset, tot_len, wanted);
516 ret_tok->sub = key_elem;
517 ret_tok->sub->last->next = value_elem;
520 #ifdef TVBPARSE_DEBUG
521 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: GOT len=%i",tot_len);
527 tvbparse_wanted_t* tvbparse_hashed(const int id,
529 tvbparse_action_t before_cb,
530 tvbparse_action_t after_cb,
531 tvbparse_wanted_t* key,
532 tvbparse_wanted_t* other,
534 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
536 tvbparse_wanted_t* el;
539 w->condition = cond_hash;
542 w->before = before_cb;
544 w->control.hash.table = wmem_map_new(wmem_epan_scope(), g_str_hash,g_str_equal);
545 w->control.hash.key = key;
546 w->control.hash.other = other;
550 while(( name = va_arg(ap,gchar*) )) {
551 el = va_arg(ap,tvbparse_wanted_t*);
552 wmem_map_insert(w->control.hash.table,name,el);
560 void tvbparse_hashed_add(tvbparse_wanted_t* w, ...) {
561 tvbparse_wanted_t* el;
567 while (( name = va_arg(ap,gchar*) )) {
568 el = va_arg(ap,tvbparse_wanted_t*);
569 wmem_map_insert(w->control.hash.table,name,el);
575 static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
579 tvbparse_elem_t* ret_tok = NULL;
581 #ifdef TVBPARSE_DEBUG
582 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: START");
585 if ( offset > tt->end_offset )
588 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
591 for(i=0; i < wanted->control.elems->len; i++) {
592 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i);
593 tvbparse_elem_t* new_elem = NULL;
595 if ( offset + w->len > tt->end_offset ) {
596 tt->recursion_depth--;
600 len = w->condition(tt, offset, w, &new_elem);
605 ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
606 ret_tok->sub->last->next = new_elem;
607 ret_tok->sub->last = new_elem;
609 ret_tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
610 ret_tok->sub = new_elem;
611 new_elem->last = new_elem;
614 tt->recursion_depth--;
619 offset += ignore_fcn(tt,offset);
622 tt->recursion_depth--;
626 #ifdef TVBPARSE_DEBUG
627 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: GOT len=%i",offset - start);
630 return offset - start;
634 tvbparse_wanted_t* tvbparse_set_seq(const int id,
636 tvbparse_action_t before_cb,
637 tvbparse_action_t after_cb,
639 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
640 tvbparse_wanted_t* el = NULL;
643 w->condition = cond_seq;
646 w->before = before_cb;
648 w->control.elems = g_ptr_array_new();
649 wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb, w);
651 va_start(ap,after_cb);
653 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
654 g_ptr_array_add(w->control.elems,el);
661 static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
662 guint got_so_far = 0;
664 tvbparse_elem_t* ret_tok = NULL;
665 #ifdef TVBPARSE_DEBUG
666 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: START");
669 if ( offset > tt->end_offset )
672 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
675 if ( wanted->min == 0 ) {
676 ret_tok = new_tok(tt,wanted->id,offset,0,wanted);
679 while (got_so_far < wanted->max) {
680 tvbparse_elem_t* new_elem = NULL;
683 if ( offset > tt->end_offset ) {
684 tt->recursion_depth--;
688 consumed = wanted->control.subelem->condition(tt, offset, wanted->control.subelem, &new_elem);
693 ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
696 ret_tok->sub->last->next = new_elem;
697 ret_tok->sub->last = new_elem;
699 ret_tok->sub = new_elem;
702 ret_tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
703 ret_tok->sub = new_elem;
713 tt->recursion_depth--;
715 #ifdef TVBPARSE_DEBUG
716 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: got num=%u",got_so_far);
719 if(got_so_far < wanted->min) {
724 #ifdef TVBPARSE_DEBUG
725 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: GOT len=%i",offset - start);
727 return offset - start;
730 tvbparse_wanted_t* tvbparse_some(const int id,
734 tvbparse_action_t before_cb,
735 tvbparse_action_t after_cb,
736 const tvbparse_wanted_t* el) {
738 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
740 g_assert(from <= to);
742 w->condition = cond_some;
747 w->before = before_cb;
749 w->control.subelem = el;
755 static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
756 tvbparse_elem_t* new_elem = NULL;
758 int target_offset = offset;
759 #ifdef TVBPARSE_DEBUG
760 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: START");
763 if ( offset + wanted->control.until.subelem->len > tt->end_offset )
766 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
770 len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem, &new_elem);
771 } while(len < 0 && target_offset+1 < tt->end_offset);
773 tt->recursion_depth--;
777 new_elem->id = wanted->id;
778 new_elem->next = NULL;
779 new_elem->last = NULL;
780 new_elem->wanted = wanted;
781 new_elem->offset = offset;
785 switch (wanted->control.until.mode) {
786 case TP_UNTIL_INCLUDE:
787 new_elem->len = target_offset - offset - 1 + len;
788 #ifdef TVBPARSE_DEBUG
789 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
791 return target_offset - offset -1 + len;
793 new_elem->len = target_offset - offset - 1;
794 #ifdef TVBPARSE_DEBUG
795 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
797 return target_offset - offset - 1 + len;
799 new_elem->len = target_offset - offset - 1;
800 #ifdef TVBPARSE_DEBUG
801 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1);
803 return target_offset - offset -1;
805 DISSECTOR_ASSERT_NOT_REACHED();
814 tvbparse_wanted_t* tvbparse_until(const int id,
816 tvbparse_action_t before_cb,
817 tvbparse_action_t after_cb,
818 const tvbparse_wanted_t* el,
819 until_mode_t until_mode) {
820 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
822 w->condition = cond_until;
823 w->control.until.mode = until_mode;
824 w->control.until.subelem = el;
827 w->before = before_cb;
834 static int cond_handle(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
835 tvbparse_wanted_t* w = *(wanted->control.handle);
836 int len = w->condition(tt, offset, w, tok);
845 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
846 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
848 w->condition = cond_handle;
849 w->control.handle = handle;
854 static int cond_end(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
855 if (offset == tt->end_offset) {
856 *tok = new_tok(tt,wanted->id,offset,0,wanted);
863 tvbparse_wanted_t* tvbparse_end_of_buffer(const int id,
865 tvbparse_action_t before_cb,
866 tvbparse_action_t after_cb) {
867 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
870 w->condition = cond_end;
872 w->before = before_cb;
879 /* these extract binary values */
881 static int cond_ft(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
884 if ( offset + wanted->len > tt->end_offset )
889 } else if (wanted->control.ftenum == FT_STRINGZ) {
890 if (( len = tvb_find_guint8(tt->tvb,offset,tt->end_offset - offset,'\0') >= 0 )) {
891 *tok = new_tok(tt,wanted->id,offset,len,wanted);
901 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(ws_in6_addr), -1, -1, -1, -1 };
903 tvbparse_wanted_t* tvbparse_ft(int id,
905 tvbparse_action_t before_cb,
906 tvbparse_action_t after_cb,
907 enum ftenum ftenum) {
908 gint len = ft_lens[ftenum];
911 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
914 w->condition = cond_ft;
916 w->control.ftenum = ftenum;
918 w->before = before_cb;
923 g_assert(! "unsupported ftenum" );
928 static int cond_ft_comp(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
929 void* l = wanted->control.number.extract(tt->tvb,offset);
930 const void* r = &(wanted->control.number.value);
932 if ( offset + wanted->len > tt->end_offset )
935 if ( wanted->control.number.comp(&l,&r) ) {
936 *tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
943 static gboolean comp_gt_i(void* lp, const void* rp) { return ( *((gint64*)lp) > *((gint64*)rp) ); }
944 static gboolean comp_ge_i(void* lp, const void* rp) { return ( *((gint64*)lp) >= *((gint64*)rp) ); }
945 static gboolean comp_eq_i(void* lp, const void* rp) { return ( *((gint64*)lp) == *((gint64*)rp) ); }
946 static gboolean comp_ne_i(void* lp, const void* rp) { return ( *((gint64*)lp) != *((gint64*)rp) ); }
947 static gboolean comp_le_i(void* lp, const void* rp) { return ( *((gint64*)lp) <= *((gint64*)rp) ); }
948 static gboolean comp_lt_i(void* lp, const void* rp) { return ( *((gint64*)lp) < *((gint64*)rp) ); }
950 static gboolean comp_gt_u(void* lp, const void* rp) { return ( *((guint64*)lp) > *((guint64*)rp) ); }
951 static gboolean comp_ge_u(void* lp, const void* rp) { return ( *((guint64*)lp) >= *((guint64*)rp) ); }
952 static gboolean comp_eq_u(void* lp, const void* rp) { return ( *((guint64*)lp) == *((guint64*)rp) ); }
953 static gboolean comp_ne_u(void* lp, const void* rp) { return ( *((guint64*)lp) != *((guint64*)rp) ); }
954 static gboolean comp_le_u(void* lp, const void* rp) { return ( *((guint64*)lp) <= *((guint64*)rp) ); }
955 static gboolean comp_lt_u(void* lp, const void* rp) { return ( *((guint64*)lp) < *((guint64*)rp) ); }
957 static gboolean comp_gt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) > *((gdouble*)rp) ); }
958 static gboolean comp_ge_f(void* lp, const void* rp) { return ( *((gdouble*)lp) >= *((gdouble*)rp) ); }
959 static gboolean comp_eq_f(void* lp, const void* rp) { return ( *((gdouble*)lp) == *((gdouble*)rp) ); }
960 static gboolean comp_ne_f(void* lp, const void* rp) { return ( *((gdouble*)lp) != *((gdouble*)rp) ); }
961 static gboolean comp_le_f(void* lp, const void* rp) { return ( *((gdouble*)lp) <= *((gdouble*)rp) ); }
962 static gboolean comp_lt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) < *((gdouble*)rp) ); }
964 static void* extract_u8(tvbuff_t* tvb, guint offset) {
965 guint64* p = wmem_new(wmem_packet_scope(), guint64);
966 *p = tvb_get_guint8(tvb,offset);
970 static void* extract_uns(tvbuff_t* tvb, guint offset) {
971 guint64* p = wmem_new(wmem_packet_scope(), guint64);
972 *p = tvb_get_ntohs(tvb,offset);
976 static void* extract_un24(tvbuff_t* tvb, guint offset) {
977 guint64* p = wmem_new(wmem_packet_scope(), guint64);
978 *p = tvb_get_ntoh24(tvb,offset);
982 static void* extract_unl(tvbuff_t* tvb, guint offset) {
983 guint64* p = wmem_new(wmem_packet_scope(), guint64);
984 *p = tvb_get_ntohl(tvb,offset);
988 static void* extract_un64(tvbuff_t* tvb, guint offset) {
989 guint64* p = wmem_new(wmem_packet_scope(), guint64);
990 *p = tvb_get_ntoh64(tvb,offset);
994 static void* extract_ules(tvbuff_t* tvb, guint offset) {
995 guint64* p = wmem_new(wmem_packet_scope(), guint64);
996 *p = tvb_get_letohs(tvb,offset);
1000 static void* extract_ule24(tvbuff_t* tvb, guint offset) {
1001 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1002 *p = tvb_get_letoh24(tvb,offset);
1006 static void* extract_ulel(tvbuff_t* tvb, guint offset) {
1007 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1008 *p = tvb_get_letohl(tvb,offset);
1012 static void* extract_ule64(tvbuff_t* tvb, guint offset) {
1013 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1014 *p = tvb_get_letoh64(tvb,offset);
1018 static void* extract_ins(tvbuff_t* tvb, guint offset) {
1019 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1020 *p = tvb_get_ntohs(tvb,offset);
1024 static void* extract_in24(tvbuff_t* tvb, guint offset) {
1025 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1026 *p = tvb_get_ntoh24(tvb,offset);
1030 static void* extract_inl(tvbuff_t* tvb, guint offset) {
1031 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1032 *p = tvb_get_ntohl(tvb,offset);
1036 static void* extract_in64(tvbuff_t* tvb, guint offset) {
1037 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1038 *p = tvb_get_ntoh64(tvb,offset);
1042 static void* extract_iles(tvbuff_t* tvb, guint offset) {
1043 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1044 *p = tvb_get_letohs(tvb,offset);
1048 static void* extract_ile24(tvbuff_t* tvb, guint offset) {
1049 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1050 *p = tvb_get_letoh24(tvb,offset);
1054 static void* extract_ilel(tvbuff_t* tvb, guint offset) {
1055 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1056 *p = tvb_get_letohl(tvb,offset);
1060 static void* extract_ile64(tvbuff_t* tvb, guint offset) {
1061 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1062 *p = tvb_get_letoh64(tvb,offset);
1066 static void* extract_inf(tvbuff_t* tvb, guint offset) {
1067 gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
1068 *p = tvb_get_ntohieee_float(tvb,offset);
1072 static void* extract_ind(tvbuff_t* tvb, guint offset) {
1073 gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
1074 *p = tvb_get_ntohieee_double(tvb,offset);
1078 static void* extract_ilef(tvbuff_t* tvb, guint offset) {
1079 gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
1080 *p = tvb_get_letohieee_float(tvb,offset);
1084 static void* extract_iled(tvbuff_t* tvb, guint offset) {
1085 gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
1086 *p = tvb_get_letohieee_double(tvb,offset);
1092 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};
1093 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};
1094 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};
1096 static gboolean (**comps[])(void*, const void*) = {comps_u,comps_i,comps_f};
1098 static void* (*extract_n[])(tvbuff_t* tvb, guint offset) = {
1099 NULL, NULL, NULL, extract_u8, extract_uns, extract_un24, extract_unl,
1100 extract_un64, extract_u8, extract_ins, extract_in24, extract_inl,
1101 extract_in64, extract_inf, extract_ind, NULL, NULL, NULL, NULL, NULL, NULL,
1102 NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL
1104 static void* (*extract_le[])(tvbuff_t* tvb, guint offset) = {
1105 NULL, NULL, NULL, extract_u8, extract_ules, extract_ule24, extract_ulel,
1106 extract_ule64, extract_u8, extract_iles, extract_ile24, extract_ilel,
1107 extract_ile64, extract_ilef, extract_iled, NULL, NULL, NULL, NULL, NULL,
1108 NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL
1111 static void* (**extracts[])(tvbuff_t* tvb, guint offset) = { extract_n, extract_le};
1114 tvbparse_wanted_t* tvbparse_ft_numcmp(int id,
1116 tvbparse_action_t before_cb,
1117 tvbparse_action_t after_cb,
1120 enum ft_cmp_op ft_cmp_op,
1122 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
1125 va_start(ap,ft_cmp_op);
1132 w->control.number.comp = comps[0][ft_cmp_op];
1133 w->control.number.value.u = va_arg(ap,guint32);
1136 w->control.number.comp = comps[0][ft_cmp_op];
1137 w->control.number.value.u = va_arg(ap,guint64);
1143 w->control.number.comp = comps[1][ft_cmp_op];
1144 w->control.number.value.i = va_arg(ap,gint32);
1147 w->control.number.comp = comps[1][ft_cmp_op];
1148 w->control.number.value.i = va_arg(ap,gint64);
1152 w->control.number.comp = comps[1][ft_cmp_op];
1153 w->control.number.value.i = va_arg(ap,gdouble);
1156 g_assert(! "comparison unsupported");
1159 w->control.number.extract = extracts[little_endian][ftenum];
1161 g_assert(w->control.number.extract && "extraction unsupported");
1164 w->condition = cond_ft_comp;
1165 w->after = after_cb;
1166 w->before = before_cb;
1175 tvbparse_wanted_t* tvbparse_quoted(const int id,
1177 tvbparse_action_t before_cb,
1178 tvbparse_action_t after_cb,
1182 gchar* esc_quot = wmem_strdup_printf(wmem_epan_scope(), "%c%c",esc,quote);
1183 gchar* quot = wmem_strdup_printf(wmem_epan_scope(), "%c",quote);
1184 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
1186 return tvbparse_set_oneof(id, data, before_cb, after_cb,
1187 tvbparse_set_seq(-1, NULL, NULL, NULL,
1189 tvbparse_set_seq(-1,NULL,NULL,NULL,
1190 tvbparse_set_oneof(-1, NULL, NULL, NULL,
1191 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
1192 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
1197 tvbparse_set_seq(-1, NULL, NULL, NULL,
1204 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
1205 const void* wanted_data _U_,
1206 tvbparse_elem_t* tok) {
1211 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
1215 const tvbparse_wanted_t* ignore) {
1216 tvbparse_t* tt = wmem_new(wmem_packet_scope(), tvbparse_t);
1218 #ifdef TVBPARSE_DEBUG
1219 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1224 tt->offset = offset;
1225 len = (len == -1) ? (int) tvb_captured_length(tvb) : len;
1226 tt->end_offset = offset + len;
1228 tt->ignore = ignore;
1229 tt->recursion_depth = 0;
1233 gboolean tvbparse_reset(tvbparse_t* tt,
1237 #ifdef TVBPARSE_DEBUG
1238 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1241 len = (len == -1) ? (int) tvb_captured_length(tt->tvb) : len;
1243 if( tvb_captured_length_remaining(tt->tvb, offset) >= len) {
1244 tt->offset = offset;
1245 tt->end_offset = offset + len;
1252 guint tvbparse_curr_offset(tvbparse_t* tt) {
1256 static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
1257 wmem_stack_t *stack = wmem_stack_new(wmem_packet_scope());
1260 if(curr->wanted->before) {
1261 #ifdef TVBPARSE_DEBUG
1262 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1264 curr->wanted->before(tt->data, curr->wanted->data, curr);
1268 wmem_stack_push(stack, curr);
1272 #ifdef TVBPARSE_DEBUG
1273 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1275 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
1280 while( !curr && wmem_stack_count(stack) > 0 ) {
1281 curr = (tvbparse_elem_t *)wmem_stack_pop(stack);
1282 #ifdef TVBPARSE_DEBUG
1283 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1285 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
1292 gboolean tvbparse_peek(tvbparse_t* tt,
1293 const tvbparse_wanted_t* wanted) {
1294 tvbparse_elem_t* tok = NULL;
1296 int offset = tt->offset;
1298 #ifdef TVBPARSE_DEBUG
1299 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: ENTER offset=%i",offset);
1302 offset += ignore_fcn(tt,offset);
1304 #ifdef TVBPARSE_DEBUG
1305 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: after ignore offset=%i",offset);
1308 consumed = wanted->condition(tt,offset,wanted,&tok);
1310 if (consumed >= 0) {
1311 #ifdef TVBPARSE_DEBUG
1312 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: GOT len=%i",consumed);
1316 #ifdef TVBPARSE_DEBUG
1317 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: NOT GOT");
1324 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
1325 const tvbparse_wanted_t* wanted) {
1326 tvbparse_elem_t* tok = NULL;
1328 int offset = tt->offset;
1330 #ifdef TVBPARSE_DEBUG
1331 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: ENTER offset=%i",offset);
1334 offset += ignore_fcn(tt,offset);
1336 #ifdef TVBPARSE_DEBUG
1337 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: after ignore offset=%i",offset);
1340 consumed = wanted->condition(tt,offset,wanted,&tok);
1342 if (consumed >= 0) {
1343 #ifdef TVBPARSE_DEBUG
1344 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: GOT len=%i",consumed);
1346 execute_callbacks(tt,tok);
1347 tt->offset = offset + consumed;
1348 #ifdef TVBPARSE_DEBUG
1349 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1359 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
1360 tvbparse_elem_t* tok = NULL;
1362 int offset = tt->offset;
1363 int target_offset = offset -1;
1365 #ifdef TVBPARSE_DEBUG
1366 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: ENTER offset=%i", tt->offset);
1370 len = wanted->condition(tt, target_offset+1, wanted, &tok);
1371 } while(len < 0 && ++target_offset < tt->end_offset);
1374 #ifdef TVBPARSE_DEBUG
1375 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len);
1377 execute_callbacks(tt,tok);
1378 tt->offset = target_offset + len;
1380 #ifdef TVBPARSE_DEBUG
1381 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1385 #ifdef TVBPARSE_DEBUG
1386 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: NOT FOUND");
1392 struct _elem_tree_stack_frame {
1394 tvbparse_elem_t* elem;
1397 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
1398 wmem_stack_t *stack = wmem_stack_new(wmem_packet_scope());
1399 struct _elem_tree_stack_frame* frame = wmem_new(wmem_packet_scope(), struct _elem_tree_stack_frame);
1405 pi = proto_tree_add_format_text(frame->tree,curr->tvb,curr->offset,curr->len);
1409 wmem_stack_push(stack, frame);
1410 frame = wmem_new(wmem_packet_scope(), struct _elem_tree_stack_frame);
1411 frame->tree = proto_item_add_subtree(pi,0);
1418 while( !curr && wmem_stack_count(stack) > 0 ) {
1419 frame = (struct _elem_tree_stack_frame *)wmem_stack_pop(stack);
1420 curr = frame->elem->next;
1427 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1432 * indent-tabs-mode: nil
1435 * vi: set shiftwidth=4 tabstop=8 expandtab:
1436 * :indentSize=4:tabSize=8:noTabs=true: