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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <epan/emem.h>
35 #include <epan/proto.h>
36 #include <epan/packet_info.h>
37 #include <epan/tvbparse.h>
40 #define TVBPARSE_DEBUG_ALL 0xffffffff
43 #define TVBPARSE_DEBUG_ 0x80000000
44 #define TVBPARSE_DEBUG_ 0x40000000
45 #define TVBPARSE_DEBUG_ 0x20000000
46 #define TVBPARSE_DEBUG_ 0x10000000
49 #define TVBPARSE_DEBUG_CHAR 0x08000000
50 #define TVBPARSE_DEBUG_CHARS 0x04000000
51 #define TVBPARSE_DEBUG_NOT_CHAR 0x02000000
52 #define TVBPARSE_DEBUG_NOT_CHARS 0x01000000
53 #define TVBPARSE_DEBUG_STRING 0x00800000
54 #define TVBPARSE_DEBUG_CASESTRING 0x00400000
55 #define TVBPARSE_DEBUG_ONEOF 0x00200000
56 #define TVBPARSE_DEBUG_HASH 0x00100000
57 #define TVBPARSE_DEBUG_SEQ 0x00080000
58 #define TVBPARSE_DEBUG_SOME 0x00040000
59 #define TVBPARSE_DEBUG_UNTIL 0x00020000
61 #define TVBPARSE_DEBUG_ 0x00010000
62 #define TVBPARSE_DEBUG_ 0x00008000
63 #define TVBPARSE_DEBUG_ 0x00004000
64 #define TVBPARSE_DEBUG_ 0x00002000
65 #define TVBPARSE_DEBUG_ 0x00001000
67 #define TVBPARSE_DEBUG_TT 0x00000800
68 #define TVBPARSE_DEBUG_CB 0x00000400
69 #define TVBPARSE_DEBUG_GET 0x00000200
70 #define TVBPARSE_DEBUG_FIND 0x00000100
71 #define TVBPARSE_DEBUG_NEWTOK 0x00000080
72 #define TVBPARSE_DEBUG_IGNORE 0x00000040
73 #define TVBPARSE_DEBUG_PEEK 0x00000020
75 #define TVBPARSE_DEBUG_ 0x00000010
76 #define TVBPARSE_DEBUG_ 0x00000008
77 #define TVBPARSE_DEBUG_ 0x00000004
78 #define TVBPARSE_DEBUG_ 0x00000002
79 #define TVBPARSE_DEBUG_ 0x00000001
83 #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
86 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
90 const tvbparse_wanted_t* wanted) {
94 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) g_warning("new_tok: id=%i offset=%u len=%u",id,offset,len);
97 tok = ep_alloc(sizeof(tvbparse_elem_t));
101 tok->offset = offset;
106 tok->wanted = wanted;
112 static int ignore_fcn(tvbparse_t* tt, int offset) {
115 tvbparse_elem_t* ignored = NULL;
117 if (!tt->ignore) return 0;
119 #ifdef TVBPARSE_DEBUG
120 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: enter");
123 while ((consumed = tt->ignore->condition(tt,offset,tt->ignore,&ignored)) > 0) {
126 #ifdef TVBPARSE_DEBUG
127 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: consumed=%i",consumed);
132 #ifdef TVBPARSE_DEBUG
133 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: len=%i",len);
140 static int cond_char (tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
144 #ifdef TVBPARSE_DEBUG
145 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: control='%s'",wanted->control.str);
148 if ( offset + 1 > tt->end_offset )
151 t = (gchar) tvb_get_guint8(tt->tvb,offset);
153 for(i = 0; (c = wanted->control.str[i]) && offset <= tt->end_offset; i++) {
155 *tok = new_tok(tt,wanted->id,offset,1,wanted);
156 #ifdef TVBPARSE_DEBUG
157 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: GOT: '%c'",c);
166 tvbparse_wanted_t* tvbparse_char(const int id,
169 tvbparse_action_t before_cb,
170 tvbparse_action_t after_cb) {
171 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
173 w->condition = cond_char;
175 w->control.str = chr;
178 w->before = before_cb;
184 static int cond_chars (tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
187 int left = tt->end_offset - offset;
189 #ifdef TVBPARSE_DEBUG
190 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars: control='%s'",wanted->control.str);
193 if ( offset + (int)wanted->min > tt->end_offset )
196 left = left < (int) wanted->max ? left : (int) wanted->max;
199 gchar t = (gchar) tvb_get_guint8(tt->tvb,offset++);
203 while ( (c = wanted->control.str[i++]) ) {
204 if (c == t) goto next_char;
214 if (length < wanted->min) {
217 *tok = new_tok(tt,wanted->id,start,length,wanted);
218 #ifdef TVBPARSE_DEBUG
219 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars: GOT len=%i",length);
225 tvbparse_wanted_t* tvbparse_chars(const int id,
230 tvbparse_action_t before_cb,
231 tvbparse_action_t after_cb) {
232 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
234 w->condition = cond_chars;
236 w->control.str = chr;
237 w->min = min_len ? min_len : 1;
238 w->max = max_len ? max_len : G_MAXINT/2;
240 w->before = before_cb;
247 static int cond_not_char(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
250 gboolean not_matched = FALSE;
252 #ifdef TVBPARSE_DEBUG
253 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: control='%s'",wanted->control.str);
256 if (! offset < tt->end_offset ) {
260 t = (gchar) tvb_get_guint8(tt->tvb,offset);
262 for(i = 0; (c = wanted->control.str[i]); i++) {
271 *tok = new_tok(tt,wanted->id,offset,1,wanted);
272 #ifdef TVBPARSE_DEBUG
273 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: GOT='%c'",t);
279 tvbparse_wanted_t* tvbparse_not_char(const int id,
282 tvbparse_action_t before_cb,
283 tvbparse_action_t after_cb) {
284 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
286 w->condition = cond_not_char;
288 w->control.str = chr;
290 w->before = before_cb;
296 static int cond_not_chars(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
298 int left = tt->end_offset - offset;
301 #ifdef TVBPARSE_DEBUG
302 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHARS) g_warning("cond_not_chars: control='%s'",wanted->control.str);
305 if ( offset + (int)wanted->min > tt->end_offset )
308 if (left < (int)wanted->min)
311 left = left <= (int)wanted->max ? left : (int)wanted->max;
315 gchar t = (gchar) tvb_get_guint8(tt->tvb,offset);
318 while ( (c = wanted->control.str[i++]) ) {
319 if (c == t) goto end_not_chars;
328 if ( length < wanted->min ) {
331 *tok = new_tok(tt,wanted->id,start,length,wanted);
332 #ifdef TVBPARSE_DEBUG
333 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHARS) g_warning("cond_not_chars: GOT len=%i",length);
339 tvbparse_wanted_t* tvbparse_not_chars(const int id,
344 tvbparse_action_t before_cb,
345 tvbparse_action_t after_cb){
346 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
348 w->condition = cond_not_chars;
350 w->control.str = chr;
352 w->min = min_len ? min_len : 1;
353 w->max = max_len ? max_len : G_MAXINT/2;
355 w->before = before_cb;
362 static int cond_string(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
363 int len = wanted->len;
364 #ifdef TVBPARSE_DEBUG
365 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: control='%s'",wanted->control.str);
368 if ( offset + wanted->len > tt->end_offset )
371 if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
372 *tok = new_tok(tt,wanted->id,offset,len,wanted);
373 #ifdef TVBPARSE_DEBUG
374 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: GOT len=%i",len);
382 tvbparse_wanted_t* tvbparse_string(const int id,
385 tvbparse_action_t before_cb,
386 tvbparse_action_t after_cb) {
387 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
389 w->condition = cond_string;
391 w->control.str = str;
392 w->len = (int) strlen(str);
394 w->before = before_cb;
400 static int cond_casestring(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
401 int len = wanted->len;
402 #ifdef TVBPARSE_DEBUG
403 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: control='%s'",wanted->control.str);
406 if ( offset + len > tt->end_offset )
409 if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
410 *tok = new_tok(tt,wanted->id,offset,len,wanted);
411 #ifdef TVBPARSE_DEBUG
412 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: GOT len=%i",len);
421 tvbparse_wanted_t* tvbparse_casestring(const int id,
424 tvbparse_action_t before_cb,
425 tvbparse_action_t after_cb) {
426 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
428 w->condition = cond_casestring;
430 w->control.str = str;
431 w->len = (int) strlen(str);
433 w->before = before_cb;
439 static int cond_one_of(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
441 #ifdef TVBPARSE_DEBUG
442 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: START");
445 if ( offset > tt->end_offset )
448 for(i=0; i < wanted->control.elems->len; i++) {
449 tvbparse_wanted_t* w = g_ptr_array_index(wanted->control.elems,i);
450 tvbparse_elem_t* new = NULL;
453 if ( offset + w->len > tt->end_offset )
456 curr_len = w->condition(tt, offset, w, &new);
459 *tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
461 #ifdef TVBPARSE_DEBUG
462 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: GOT len=%i",curr_len);
471 tvbparse_wanted_t* tvbparse_set_oneof(const int id,
473 tvbparse_action_t before_cb,
474 tvbparse_action_t after_cb,
476 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
480 w->condition = cond_one_of;
483 w->before = before_cb;
485 w->control.elems = g_ptr_array_new();
487 va_start(ap,after_cb);
489 while(( el = va_arg(ap,tvbparse_t*) )) {
490 g_ptr_array_add(w->control.elems,el);
498 static int cond_hash(tvbparse_t* tt, const int offset, const tvbparse_wanted_t* wanted, tvbparse_elem_t** tok) {
501 tvbparse_elem_t* key_elem = NULL;
502 tvbparse_wanted_t* value_wanted = NULL;
504 tvbparse_elem_t* value_elem = NULL;
506 tvbparse_elem_t* ret_tok;
508 #ifdef TVBPARSE_DEBUG
509 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: START");
512 if ( offset > tt->end_offset )
515 key_len = wanted->control.hash.key->condition(tt, offset, wanted->control.hash.key, &key_elem);
520 key = tvb_get_ephemeral_string(key_elem->tvb,key_elem->offset,key_elem->len);
521 #ifdef TVBPARSE_DEBUG
522 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: got key='%s'",key);
525 if ((value_wanted = g_hash_table_lookup(wanted->control.hash.table,key))) {
526 value_len = value_wanted->condition(tt, offset + key_len, value_wanted, &value_elem);
527 } else if (wanted->control.hash.other) {
528 value_len = wanted->control.hash.other->condition(tt, offset+key_len, wanted->control.hash.other, &value_elem);
535 tot_len = key_len + value_len;
537 ret_tok = new_tok(tt, value_elem->id, offset, tot_len, wanted);
538 ret_tok->sub = key_elem;
539 ret_tok->sub->last->next = value_elem;
542 #ifdef TVBPARSE_DEBUG
543 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: GOT len=%i",tot_len);
549 tvbparse_wanted_t* tvbparse_hashed(const int id,
551 tvbparse_action_t before_cb,
552 tvbparse_action_t after_cb,
553 tvbparse_wanted_t* key,
554 tvbparse_wanted_t* other,
556 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
558 tvbparse_wanted_t* el;
561 w->condition = cond_hash;
564 w->before = before_cb;
566 w->control.hash.table = g_hash_table_new(g_str_hash,g_str_equal);
567 w->control.hash.key = key;
568 w->control.hash.other = other;
572 while(( name = va_arg(ap,gchar*) )) {
573 el = va_arg(ap,tvbparse_wanted_t*);
574 g_hash_table_insert(w->control.hash.table,name,el);
582 void tvbparse_hashed_add(tvbparse_wanted_t* w, ...) {
583 tvbparse_wanted_t* el;
589 while (( name = va_arg(ap,gchar*) )) {
590 el = va_arg(ap,tvbparse_wanted_t*);
591 g_hash_table_insert(w->control.hash.table,name,el);
597 static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
601 tvbparse_elem_t* ret_tok = NULL;
603 if ( offset > tt->end_offset )
605 #ifdef TVBPARSE_DEBUG
606 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: START");
609 for(i=0; i < wanted->control.elems->len; i++) {
610 tvbparse_wanted_t* w = g_ptr_array_index(wanted->control.elems,i);
611 tvbparse_elem_t* new = NULL;
613 if ( offset + w->len > tt->end_offset )
617 len = w->condition(tt, offset, w, &new);
621 ret_tok->len = (new->offset - ret_tok->offset) + new->len;
622 ret_tok->sub->last->next = new;
623 ret_tok->sub->last = new;
625 ret_tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
634 offset += ignore_fcn(tt,offset);
639 #ifdef TVBPARSE_DEBUG
640 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: GOT len=%i",offset - start);
643 return offset - start;
647 tvbparse_wanted_t* tvbparse_set_seq(const int id,
649 tvbparse_action_t before_cb,
650 tvbparse_action_t after_cb,
652 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
653 tvbparse_wanted_t* el = NULL;
656 w->condition = cond_seq;
659 w->before = before_cb;
661 w->control.elems = g_ptr_array_new();
663 va_start(ap,after_cb);
665 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
666 g_ptr_array_add(w->control.elems,el);
673 static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
674 guint got_so_far = 0;
676 tvbparse_elem_t* ret_tok = NULL;
677 #ifdef TVBPARSE_DEBUG
678 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: START");
681 if ( offset > tt->end_offset )
684 if ( wanted->min == 0 ) {
685 ret_tok = new_tok(tt,wanted->id,offset,0,wanted);
688 while (got_so_far < wanted->max) {
689 tvbparse_elem_t* new = NULL;
692 if ( offset > tt->end_offset )
695 consumed = wanted->control.subelem->condition(tt, offset, wanted->control.subelem, &new);
699 ret_tok->len = (new->offset - ret_tok->offset) + new->len;
702 ret_tok->sub->last->next = new;
703 ret_tok->sub->last = new;
708 ret_tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
719 #ifdef TVBPARSE_DEBUG
720 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: got num=%u",got_so_far);
723 if(got_so_far < wanted->min) {
728 #ifdef TVBPARSE_DEBUG
729 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: GOT len=%i",offset - start);
731 return offset - start;
734 tvbparse_wanted_t* tvbparse_some(const int id,
738 tvbparse_action_t before_cb,
739 tvbparse_action_t after_cb,
740 const tvbparse_wanted_t* el) {
742 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
744 g_assert(from <= to);
746 w->condition = cond_some;
751 w->before = before_cb;
753 w->control.subelem = el;
759 static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
760 tvbparse_elem_t* new = NULL;
762 int target_offset = offset;
763 #ifdef TVBPARSE_DEBUG
764 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: START");
767 if ( offset + wanted->control.until.subelem->len > tt->end_offset )
771 len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem, &new);
772 } while(len < 0 && target_offset+1 < tt->end_offset);
776 new->id = wanted->id;
779 new->wanted = wanted;
780 new->offset = offset;
784 switch (wanted->control.until.mode) {
785 case TP_UNTIL_INCLUDE:
786 new->len = target_offset - offset - 1 + len;
787 #ifdef TVBPARSE_DEBUG
788 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
790 return target_offset - offset -1 + len;
792 new->len = target_offset - offset - 1;
793 #ifdef TVBPARSE_DEBUG
794 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
796 return target_offset - offset - 1 + len;
798 new->len = target_offset - offset - 1;
799 #ifdef TVBPARSE_DEBUG
800 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1);
802 return target_offset - offset -1;
804 DISSECTOR_ASSERT_NOT_REACHED();
813 tvbparse_wanted_t* tvbparse_until(const int id,
815 tvbparse_action_t before_cb,
816 tvbparse_action_t after_cb,
817 const tvbparse_wanted_t* el,
818 until_mode_t until_mode) {
819 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
821 w->condition = cond_until;
822 w->control.until.mode = until_mode;
823 w->control.until.subelem = el;
826 w->before = before_cb;
832 static int cond_handle(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
833 tvbparse_wanted_t* w = *(wanted->control.handle);
834 int len = w->condition(tt, offset, w, tok);
843 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
844 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
846 w->condition = cond_handle;
847 w->control.handle = handle;
852 static int cond_end(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
853 if (offset == tt->end_offset) {
854 *tok = new_tok(tt,wanted->id,offset,0,wanted);
861 tvbparse_wanted_t* tvbparse_end_of_buffer(const int id,
863 tvbparse_action_t before_cb,
864 tvbparse_action_t after_cb) {
865 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
868 w->condition = cond_end;
870 w->before = before_cb;
878 /* these extract binary values */
880 static int cond_ft(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
883 if ( offset + wanted->len > tt->end_offset )
888 } else if (wanted->control.ftenum == FT_STRINGZ) {
889 if (( len = tvb_find_guint8(tt->tvb,offset,tt->end_offset - offset,'\0') >= 0 )) {
890 *tok = new_tok(tt,wanted->id,offset,len,wanted);
900 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 };
902 tvbparse_wanted_t* tvbparse_ft(int id,
904 tvbparse_action_t before_cb,
905 tvbparse_action_t after_cb,
906 enum ftenum ftenum) {
907 gint len = ft_lens[ftenum];
910 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
913 w->condition = cond_ft;
915 w->control.ftenum = ftenum;
917 w->before = before_cb;
922 g_assert(! "unsupported ftenum" );
927 static int cond_ft_comp(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
928 void* l = wanted->control.number.extract(tt->tvb,offset);
929 const void* r = &(wanted->control.number.value);
931 if ( offset + wanted->len > tt->end_offset )
934 if ( wanted->control.number.comp(&l,&r) ) {
935 *tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
942 static gboolean comp_gt_i(void* lp, const void* rp) { return ( *((gint64*)lp) > *((gint64*)rp) ); }
943 static gboolean comp_ge_i(void* lp, const void* rp) { return ( *((gint64*)lp) >= *((gint64*)rp) ); }
944 static gboolean comp_eq_i(void* lp, const void* rp) { return ( *((gint64*)lp) == *((gint64*)rp) ); }
945 static gboolean comp_ne_i(void* lp, const void* rp) { return ( *((gint64*)lp) != *((gint64*)rp) ); }
946 static gboolean comp_le_i(void* lp, const void* rp) { return ( *((gint64*)lp) <= *((gint64*)rp) ); }
947 static gboolean comp_lt_i(void* lp, const void* rp) { return ( *((gint64*)lp) < *((gint64*)rp) ); }
949 static gboolean comp_gt_u(void* lp, const void* rp) { return ( *((guint64*)lp) > *((guint64*)rp) ); }
950 static gboolean comp_ge_u(void* lp, const void* rp) { return ( *((guint64*)lp) >= *((guint64*)rp) ); }
951 static gboolean comp_eq_u(void* lp, const void* rp) { return ( *((guint64*)lp) == *((guint64*)rp) ); }
952 static gboolean comp_ne_u(void* lp, const void* rp) { return ( *((guint64*)lp) != *((guint64*)rp) ); }
953 static gboolean comp_le_u(void* lp, const void* rp) { return ( *((guint64*)lp) <= *((guint64*)rp) ); }
954 static gboolean comp_lt_u(void* lp, const void* rp) { return ( *((guint64*)lp) < *((guint64*)rp) ); }
956 static gboolean comp_gt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) > *((gdouble*)rp) ); }
957 static gboolean comp_ge_f(void* lp, const void* rp) { return ( *((gdouble*)lp) >= *((gdouble*)rp) ); }
958 static gboolean comp_eq_f(void* lp, const void* rp) { return ( *((gdouble*)lp) == *((gdouble*)rp) ); }
959 static gboolean comp_ne_f(void* lp, const void* rp) { return ( *((gdouble*)lp) != *((gdouble*)rp) ); }
960 static gboolean comp_le_f(void* lp, const void* rp) { return ( *((gdouble*)lp) <= *((gdouble*)rp) ); }
961 static gboolean comp_lt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) < *((gdouble*)rp) ); }
963 static void* extract_u8(tvbuff_t* tvb, guint offset) {
964 guint64* p = ep_new(guint64);
965 *p = tvb_get_guint8(tvb,offset);
969 static void* extract_uns(tvbuff_t* tvb, guint offset) {
970 guint64* p = ep_new(guint64);
971 *p = tvb_get_ntohs(tvb,offset);
975 static void* extract_un24(tvbuff_t* tvb, guint offset) {
976 guint64* p = ep_new(guint64);
977 *p = tvb_get_ntoh24(tvb,offset);
981 static void* extract_unl(tvbuff_t* tvb, guint offset) {
982 guint64* p = ep_new(guint64);
983 *p = tvb_get_ntohl(tvb,offset);
987 static void* extract_un64(tvbuff_t* tvb, guint offset) {
988 guint64* p = ep_new(guint64);
989 *p = tvb_get_ntoh64(tvb,offset);
993 static void* extract_ules(tvbuff_t* tvb, guint offset) {
994 guint64* p = ep_new(guint64);
995 *p = tvb_get_letohs(tvb,offset);
999 static void* extract_ule24(tvbuff_t* tvb, guint offset) {
1000 guint64* p = ep_new(guint64);
1001 *p = tvb_get_letoh24(tvb,offset);
1005 static void* extract_ulel(tvbuff_t* tvb, guint offset) {
1006 guint64* p = ep_new(guint64);
1007 *p = tvb_get_letohl(tvb,offset);
1011 static void* extract_ule64(tvbuff_t* tvb, guint offset) {
1012 guint64* p = ep_new(guint64);
1013 *p = tvb_get_letoh64(tvb,offset);
1017 static void* extract_ins(tvbuff_t* tvb, guint offset) {
1018 guint64* p = ep_new(guint64);
1019 *p = tvb_get_ntohs(tvb,offset);
1023 static void* extract_in24(tvbuff_t* tvb, guint offset) {
1024 guint64* p = ep_new(guint64);
1025 *p = tvb_get_ntoh24(tvb,offset);
1029 static void* extract_inl(tvbuff_t* tvb, guint offset) {
1030 guint64* p = ep_new(guint64);
1031 *p = tvb_get_ntohl(tvb,offset);
1035 static void* extract_in64(tvbuff_t* tvb, guint offset) {
1036 guint64* p = ep_new(guint64);
1037 *p = tvb_get_ntoh64(tvb,offset);
1041 static void* extract_iles(tvbuff_t* tvb, guint offset) {
1042 guint64* p = ep_new(guint64);
1043 *p = tvb_get_letohs(tvb,offset);
1047 static void* extract_ile24(tvbuff_t* tvb, guint offset) {
1048 guint64* p = ep_new(guint64);
1049 *p = tvb_get_letoh24(tvb,offset);
1053 static void* extract_ilel(tvbuff_t* tvb, guint offset) {
1054 guint64* p = ep_new(guint64);
1055 *p = tvb_get_letohl(tvb,offset);
1059 static void* extract_ile64(tvbuff_t* tvb, guint offset) {
1060 guint64* p = ep_new(guint64);
1061 *p = tvb_get_letoh64(tvb,offset);
1065 static void* extract_inf(tvbuff_t* tvb, guint offset) {
1066 gdouble* p = ep_new(gdouble);
1067 *p = tvb_get_ntohieee_float(tvb,offset);
1071 static void* extract_ind(tvbuff_t* tvb, guint offset) {
1072 gdouble* p = ep_new(gdouble);
1073 *p = tvb_get_ntohieee_double(tvb,offset);
1077 static void* extract_ilef(tvbuff_t* tvb, guint offset) {
1078 gdouble* p = ep_new(gdouble);
1079 *p = tvb_get_letohieee_float(tvb,offset);
1083 static void* extract_iled(tvbuff_t* tvb, guint offset) {
1084 gdouble* p = ep_new(gdouble);
1085 *p = tvb_get_letohieee_double(tvb,offset);
1091 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};
1092 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};
1093 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};
1095 static gboolean (**comps[])(void*, const void*) = {comps_u,comps_i,comps_f};
1097 static void* (*extract_n[])(tvbuff_t* tvb, guint offset) = { NULL, NULL, NULL, extract_u8, extract_uns, extract_un24, extract_unl, extract_un64, extract_u8, extract_ins, extract_in24, extract_inl, extract_in64, extract_inf, extract_ind, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL };
1098 static void* (*extract_le[])(tvbuff_t* tvb, guint offset) = { NULL, NULL, NULL, extract_u8, extract_ules, extract_ule24, extract_ulel, extract_ule64, extract_u8, extract_iles, extract_ile24, extract_ilel, extract_ile64, extract_ilef, extract_iled, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL };
1100 static void* (**extracts[])(tvbuff_t* tvb, guint offset) = { extract_n, extract_le};
1103 tvbparse_wanted_t* tvbparse_ft_numcmp(int id,
1105 tvbparse_action_t before_cb,
1106 tvbparse_action_t after_cb,
1109 enum ft_cmp_op ft_cmp_op,
1111 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
1114 va_start(ap,ft_cmp_op);
1121 w->control.number.comp = comps[0][ft_cmp_op];
1122 w->control.number.value.u = va_arg(ap,guint32);
1125 w->control.number.comp = comps[0][ft_cmp_op];
1126 w->control.number.value.u = va_arg(ap,guint64);
1132 w->control.number.comp = comps[1][ft_cmp_op];
1133 w->control.number.value.i = va_arg(ap,gint32);
1136 w->control.number.comp = comps[1][ft_cmp_op];
1137 w->control.number.value.i = va_arg(ap,gint64);
1141 w->control.number.comp = comps[1][ft_cmp_op];
1142 w->control.number.value.i = va_arg(ap,gdouble);
1145 g_assert(! "comparison unsupported");
1148 w->control.number.extract = extracts[little_endian][ftenum];
1150 g_assert(w->control.number.extract && "extraction unsupported");
1153 w->condition = cond_ft_comp;
1154 w->after = after_cb;
1155 w->before = before_cb;
1164 tvbparse_wanted_t* tvbparse_quoted(const int id,
1166 tvbparse_action_t before_cb,
1167 tvbparse_action_t after_cb,
1171 gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
1172 gchar* quot = g_strdup_printf("%c",quote);
1173 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
1175 return tvbparse_set_oneof(id, data, before_cb, after_cb,
1176 tvbparse_set_seq(-1, NULL, NULL, NULL,
1178 tvbparse_set_seq(-1,NULL,NULL,NULL,
1179 tvbparse_set_oneof(-1, NULL, NULL, NULL,
1180 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
1181 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
1186 tvbparse_set_seq(-1, NULL, NULL, NULL,
1193 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
1194 const void* wanted_data _U_,
1195 tvbparse_elem_t* tok) {
1200 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
1204 const tvbparse_wanted_t* ignore) {
1205 tvbparse_t* tt = ep_alloc(sizeof(tvbparse_t));
1207 #ifdef TVBPARSE_DEBUG
1208 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1213 tt->offset = offset;
1214 len = (len == -1) ? (int) tvb_length(tvb) : len;
1215 tt->end_offset = offset + len;
1217 tt->ignore = ignore;
1221 gboolean tvbparse_reset(tvbparse_t* tt,
1225 #ifdef TVBPARSE_DEBUG
1226 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1229 len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
1231 if( tvb_length_remaining(tt->tvb, offset) >= len) {
1232 tt->offset = offset;
1233 tt->end_offset = offset + len;
1240 guint tvbparse_curr_offset(tvbparse_t* tt) {
1244 static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
1245 ep_stack_t stack = ep_stack_new();
1248 if(curr->wanted->before) {
1249 #ifdef TVBPARSE_DEBUG
1250 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1252 curr->wanted->before(tt->data, curr->wanted->data, curr);
1256 ep_stack_push(stack,curr);
1260 #ifdef TVBPARSE_DEBUG
1261 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1263 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
1268 while( !curr && ep_stack_peek(stack) ) {
1269 curr = ep_stack_pop(stack);
1270 #ifdef TVBPARSE_DEBUG
1271 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1273 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
1280 gboolean tvbparse_peek(tvbparse_t* tt,
1281 const tvbparse_wanted_t* wanted) {
1282 tvbparse_elem_t* tok = NULL;
1284 int offset = tt->offset;
1286 #ifdef TVBPARSE_DEBUG
1287 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: ENTER offset=%i",offset);
1290 offset += ignore_fcn(tt,offset);
1292 #ifdef TVBPARSE_DEBUG
1293 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: after ignore offset=%i",offset);
1296 consumed = wanted->condition(tt,offset,wanted,&tok);
1298 if (consumed >= 0) {
1299 #ifdef TVBPARSE_DEBUG
1300 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: GOT len=%i",consumed);
1304 #ifdef TVBPARSE_DEBUG
1305 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: NOT GOT");
1312 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
1313 const tvbparse_wanted_t* wanted) {
1314 tvbparse_elem_t* tok = NULL;
1316 int offset = tt->offset;
1318 #ifdef TVBPARSE_DEBUG
1319 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: ENTER offset=%i",offset);
1322 offset += ignore_fcn(tt,offset);
1324 #ifdef TVBPARSE_DEBUG
1325 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: after ignore offset=%i",offset);
1328 consumed = wanted->condition(tt,offset,wanted,&tok);
1330 if (consumed >= 0) {
1331 #ifdef TVBPARSE_DEBUG
1332 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: GOT len=%i",consumed);
1334 execute_callbacks(tt,tok);
1335 tt->offset = offset + consumed;
1336 #ifdef TVBPARSE_DEBUG
1337 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1347 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
1348 tvbparse_elem_t* tok = NULL;
1350 int offset = tt->offset;
1351 int target_offset = offset -1;
1353 #ifdef TVBPARSE_DEBUG
1354 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: ENTER offset=%i", tt->offset);
1358 len = wanted->condition(tt, target_offset+1, wanted, &tok);
1359 } while(len < 0 && ++target_offset < tt->end_offset);
1362 #ifdef TVBPARSE_DEBUG
1363 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len);
1365 execute_callbacks(tt,tok);
1366 tt->offset = target_offset + len;
1368 #ifdef TVBPARSE_DEBUG
1369 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1373 #ifdef TVBPARSE_DEBUG
1374 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: NOT FOUND");
1380 struct _elem_tree_stack_frame {
1382 tvbparse_elem_t* elem;
1385 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
1386 ep_stack_t stack = ep_stack_new();
1387 struct _elem_tree_stack_frame* frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
1393 pi = proto_tree_add_text(frame->tree,curr->tvb,curr->offset,curr->len,"%s",tvb_format_text(curr->tvb,curr->offset,curr->len));
1397 ep_stack_push(stack,frame);
1398 frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
1399 frame->tree = proto_item_add_subtree(pi,0);
1406 while( !curr && ep_stack_peek(stack) ) {
1407 frame = ep_stack_pop(stack);
1408 curr = frame->elem->next;