3 * Copyright 2005, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
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
42 /*#define TVBPARSE_DEBUG_ 0x80000000
43 #define TVBPARSE_DEBUG_ 0x40000000
44 #define TVBPARSE_DEBUG_ 0x20000000
45 #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
58 /*#define TVBPARSE_DEBUG_ 0x00010000
59 #define TVBPARSE_DEBUG_ 0x00008000
60 #define TVBPARSE_DEBUG_ 0x00004000
61 #define TVBPARSE_DEBUG_ 0x00002000
62 #define TVBPARSE_DEBUG_ 0x00001000*/
64 #define TVBPARSE_DEBUG_TT 0x00000800
65 #define TVBPARSE_DEBUG_CB 0x00000400
66 #define TVBPARSE_DEBUG_GET 0x00000200
67 #define TVBPARSE_DEBUG_FIND 0x00000100
68 #define TVBPARSE_DEBUG_NEWTOK 0x00000080
69 #define TVBPARSE_DEBUG_IGNORE 0x00000040
70 #define TVBPARSE_DEBUG_PEEK 0x00000020
71 /*#define TVBPARSE_DEBUG_ 0x00000010
72 #define TVBPARSE_DEBUG_ 0x00000008
73 #define TVBPARSE_DEBUG_ 0x00000004
74 #define TVBPARSE_DEBUG_ 0x00000002
75 #define TVBPARSE_DEBUG_ 0x00000001*/
78 #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
81 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
85 const tvbparse_wanted_t* wanted) {
89 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) g_warning("new_tok: id=%i offset=%u len=%u",id,offset,len);
92 tok = ep_alloc(sizeof(tvbparse_elem_t));
101 tok->wanted = wanted;
107 static int ignore(tvbparse_t* tt,int offset) {
110 tvbparse_elem_t* ignored = NULL;
112 if (!tt->ignore) return 0;
114 #ifdef TVBPARSE_DEBUG
115 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: enter");
118 while ((consumed = tt->ignore->condition(tt,offset,tt->ignore,&ignored)) > 0) {
121 #ifdef TVBPARSE_DEBUG
122 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: consumed=%i",consumed);
127 #ifdef TVBPARSE_DEBUG
128 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: len=%i",len);
135 static int cond_char (tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
139 #ifdef TVBPARSE_DEBUG
140 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: control='%s'",wanted->control.str);
143 if ( offset + 1 > tt->end_offset )
146 t = (gchar) tvb_get_guint8(tt->tvb,offset);
148 for(i = 0; (c = wanted->control.str[i]) && offset <= tt->end_offset; i++) {
150 *tok = new_tok(tt,wanted->id,offset,1,wanted);
151 #ifdef TVBPARSE_DEBUG
152 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: GOT: '%c'",c);
161 tvbparse_wanted_t* tvbparse_char(int id,
164 tvbparse_action_t before_cb,
165 tvbparse_action_t after_cb) {
166 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
168 w->condition = cond_char;
170 w->control.str = chr;
173 w->before = before_cb;
179 static int cond_chars (tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
182 int left = tt->end_offset - offset;
184 #ifdef TVBPARSE_DEBUG
185 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars: control='%s'",wanted->control.str);
188 if ( offset + (int)wanted->min > tt->end_offset )
191 left = left < (int) wanted->max ? left : (int) wanted->max;
194 gchar t = (gchar) tvb_get_guint8(tt->tvb,offset++);
198 while ( (c = wanted->control.str[i++]) ) {
199 if (c == t) goto next_char;
209 if (length < wanted->min) {
212 *tok = new_tok(tt,wanted->id,start,length,wanted);
213 #ifdef TVBPARSE_DEBUG
214 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars: GOT len=%i",length);
220 tvbparse_wanted_t* tvbparse_chars(int id,
225 tvbparse_action_t before_cb,
226 tvbparse_action_t after_cb) {
227 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
229 w->condition = cond_chars;
231 w->control.str = chr;
232 w->min = min_len ? min_len : 1;
233 w->max = max_len ? max_len : G_MAXINT/2;
235 w->before = before_cb;
242 static int cond_not_char(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
245 gboolean not_matched = FALSE;
247 #ifdef TVBPARSE_DEBUG
248 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: control='%s'",wanted->control.str);
251 if (! offset < tt->end_offset ) {
255 t = (gchar) tvb_get_guint8(tt->tvb,offset);
257 for(i = 0; (c = wanted->control.str[i]); i++) {
266 *tok = new_tok(tt,wanted->id,offset,1,wanted);
267 #ifdef TVBPARSE_DEBUG
268 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: GOT='%c'",t);
274 tvbparse_wanted_t* tvbparse_not_char(int id,
277 tvbparse_action_t before_cb,
278 tvbparse_action_t after_cb) {
279 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
281 w->condition = cond_not_char;
283 w->control.str = chr;
285 w->before = before_cb;
291 static int cond_not_chars(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
293 int left = tt->end_offset - offset;
296 #ifdef TVBPARSE_DEBUG
297 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHARS) g_warning("cond_not_chars: control='%s'",wanted->control.str);
300 if ( offset + (int)wanted->min > tt->end_offset )
303 if (left < (int)wanted->min)
306 left = left <= (int)wanted->max ? left : (int)wanted->max;
310 gchar t = (gchar) tvb_get_guint8(tt->tvb,offset);
313 while ( (c = wanted->control.str[i++]) ) {
314 if (c == t) goto end_not_chars;
323 if ( length < wanted->min ) {
326 *tok = new_tok(tt,wanted->id,start,length,wanted);
327 #ifdef TVBPARSE_DEBUG
328 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHARS) g_warning("cond_not_chars: GOT len=%i",length);
334 tvbparse_wanted_t* tvbparse_not_chars(int id,
339 tvbparse_action_t before_cb,
340 tvbparse_action_t after_cb){
341 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
343 w->condition = cond_not_chars;
345 w->control.str = chr;
347 w->min = min_len ? min_len : 1;
348 w->max = max_len ? max_len : G_MAXINT/2;
350 w->before = before_cb;
357 static int cond_string(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
358 int len = wanted->len;
359 #ifdef TVBPARSE_DEBUG
360 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: control='%s'",wanted->control.str);
363 if ( offset + wanted->len > tt->end_offset )
366 if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
367 *tok = new_tok(tt,wanted->id,offset,len,wanted);
368 #ifdef TVBPARSE_DEBUG
369 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: GOT len=%i",len);
377 tvbparse_wanted_t* tvbparse_string(int id,
380 tvbparse_action_t before_cb,
381 tvbparse_action_t after_cb) {
382 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
384 w->condition = cond_string;
386 w->control.str = str;
387 w->len = strlen(str);
389 w->before = before_cb;
395 static int cond_casestring(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
396 int len = wanted->len;
397 #ifdef TVBPARSE_DEBUG
398 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: control='%s'",wanted->control.str);
401 if ( offset + len > tt->end_offset )
404 if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
405 *tok = new_tok(tt,wanted->id,offset,len,wanted);
406 #ifdef TVBPARSE_DEBUG
407 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: GOT len=%i",len);
416 tvbparse_wanted_t* tvbparse_casestring(int id,
419 tvbparse_action_t before_cb,
420 tvbparse_action_t after_cb) {
421 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
423 w->condition = cond_casestring;
425 w->control.str = str;
426 w->len = strlen(str);
428 w->before = before_cb;
434 static int cond_one_of(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
436 #ifdef TVBPARSE_DEBUG
437 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: START");
440 if ( offset > tt->end_offset )
443 for(i=0; i < wanted->control.elems->len; i++) {
444 tvbparse_wanted_t* w = g_ptr_array_index(wanted->control.elems,i);
445 tvbparse_elem_t* new = NULL;
448 if ( offset + w->len > tt->end_offset )
451 curr_len = w->condition(tt, offset, w, &new);
454 *tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
456 #ifdef TVBPARSE_DEBUG
457 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: GOT len=%i",curr_len);
466 tvbparse_wanted_t* tvbparse_set_oneof(int id,
468 tvbparse_action_t before_cb,
469 tvbparse_action_t after_cb,
471 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
475 w->condition = cond_one_of;
478 w->before = before_cb;
480 w->control.elems = g_ptr_array_new();
482 va_start(ap,after_cb);
484 while(( el = va_arg(ap,tvbparse_t*) )) {
485 g_ptr_array_add(w->control.elems,el);
493 static int cond_hash(tvbparse_t* tt, int offset, const tvbparse_wanted_t* wanted, tvbparse_elem_t** tok) {
496 tvbparse_elem_t* key_elem = NULL;
497 tvbparse_wanted_t* value_wanted = NULL;
499 tvbparse_elem_t* value_elem = NULL;
502 #ifdef TVBPARSE_DEBUG
503 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: START");
506 tvbparse_elem_t* ret_tok;
507 if ( offset > tt->end_offset )
510 key_len = wanted->control.hash.key->condition(tt, offset, wanted->control.hash.key, &key_elem);
515 key = tvb_get_ephemeral_string(key_elem->tvb,key_elem->offset,key_elem->len);
516 #ifdef TVBPARSE_DEBUG
517 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: got key='%s'",key);
520 if ((value_wanted = g_hash_table_lookup(wanted->control.hash.table,key))) {
521 value_len = value_wanted->condition(tt, offset + key_len, value_wanted, &value_elem);
522 } else if (wanted->control.hash.other) {
523 value_len = wanted->control.hash.other->condition(tt, offset+key_len, wanted->control.hash.other, &value_elem);
530 tot_len = key_len + value_len;
532 ret_tok = new_tok(tt, value_elem->id, offset, tot_len, wanted);
533 ret_tok->sub = key_elem;
534 ret_tok->sub->last->next = value_elem;
537 #ifdef TVBPARSE_DEBUG
538 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: GOT len=%i",tot_len);
544 tvbparse_wanted_t* tvbparse_hashed(int id,
546 tvbparse_action_t before_cb,
547 tvbparse_action_t after_cb,
548 tvbparse_wanted_t* key,
549 tvbparse_wanted_t* other,
551 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
553 tvbparse_wanted_t* el;
556 w->condition = cond_hash;
559 w->before = before_cb;
561 w->control.hash.table = g_hash_table_new(g_str_hash,g_str_equal);
562 w->control.hash.key = key;
563 w->control.hash.other = other;
567 while(( name = va_arg(ap,gchar*) )) {
568 el = va_arg(ap,tvbparse_wanted_t*);
569 g_hash_table_insert(w->control.hash.table,name,el);
577 void tvbparse_hashed_add(tvbparse_wanted_t* w, ...) {
578 tvbparse_wanted_t* el;
584 while (( name = va_arg(ap,gchar*) )) {
585 el = va_arg(ap,tvbparse_wanted_t*);
586 g_hash_table_insert(w->control.hash.table,name,el);
592 static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
596 tvbparse_elem_t* ret_tok = NULL;
598 if ( offset > tt->end_offset )
600 #ifdef TVBPARSE_DEBUG
601 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: START");
604 for(i=0; i < wanted->control.elems->len; i++) {
605 tvbparse_wanted_t* w = g_ptr_array_index(wanted->control.elems,i);
606 tvbparse_elem_t* new = NULL;
608 if ( offset + w->len > tt->end_offset )
612 len = w->condition(tt, offset, w, &new);
616 ret_tok->len = (new->offset - ret_tok->offset) + new->len;
617 ret_tok->sub->last->next = new;
618 ret_tok->sub->last = new;
620 ret_tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
629 offset += ignore(tt,offset);
634 #ifdef TVBPARSE_DEBUG
635 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: GOT len=%i",offset - start);
638 return offset - start;
642 tvbparse_wanted_t* tvbparse_set_seq(int id,
644 tvbparse_action_t before_cb,
645 tvbparse_action_t after_cb,
647 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
648 tvbparse_wanted_t* el = NULL;
651 w->condition = cond_seq;
654 w->before = before_cb;
656 w->control.elems = g_ptr_array_new();
658 va_start(ap,after_cb);
660 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
661 g_ptr_array_add(w->control.elems,el);
668 static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
669 guint got_so_far = 0;
671 tvbparse_elem_t* ret_tok = NULL;
672 #ifdef TVBPARSE_DEBUG
673 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: START");
676 if ( offset > tt->end_offset )
679 if ( wanted->min == 0 ) {
680 ret_tok = new_tok(tt,wanted->id,tt->offset,0,wanted);
683 while (got_so_far < wanted->max) {
684 tvbparse_elem_t* new = NULL;
687 if ( offset > tt->end_offset )
690 consumed = wanted->control.subelem->condition(tt, offset, wanted->control.subelem, &new);
694 ret_tok->len = (new->offset - ret_tok->offset) + new->len;
697 ret_tok->sub->last->next = new;
698 ret_tok->sub->last = new;
703 ret_tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
714 #ifdef TVBPARSE_DEBUG
715 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: got num=%u",got_so_far);
718 if(got_so_far < wanted->min) {
723 #ifdef TVBPARSE_DEBUG
724 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: GOT len=%i",offset - start);
726 return offset - start;
729 tvbparse_wanted_t* tvbparse_some(int id,
733 tvbparse_action_t before_cb,
734 tvbparse_action_t after_cb,
735 const tvbparse_wanted_t* el) {
737 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
739 g_assert(from <= to);
741 w->condition = cond_some;
746 w->before = before_cb;
748 w->control.subelem = el;
754 static int cond_until(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
755 tvbparse_elem_t* new = NULL;
757 int target_offset = offset;
758 #ifdef TVBPARSE_DEBUG
759 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: START");
762 if ( offset + wanted->control.until.subelem->len > tt->end_offset )
766 len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem, &new);
767 } while(len < 0 && target_offset+1 < tt->end_offset);
771 new->id = wanted->id;
774 new->wanted = wanted;
775 new->offset = offset;
779 switch (wanted->control.until.mode) {
780 case TP_UNTIL_INCLUDE:
781 new->len = target_offset - offset - 1 + len;
782 #ifdef TVBPARSE_DEBUG
783 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
785 return target_offset - offset -1 + len;
787 new->len = target_offset - offset - 1;
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->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);
797 return target_offset - offset -1;
799 DISSECTOR_ASSERT_NOT_REACHED();
808 tvbparse_wanted_t* tvbparse_until(int id,
810 tvbparse_action_t before_cb,
811 tvbparse_action_t after_cb,
812 const tvbparse_wanted_t* el,
813 until_mode_t until_mode) {
814 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
816 w->condition = cond_until;
817 w->control.until.mode = until_mode;
818 w->control.until.subelem = el;
821 w->before = before_cb;
827 static int cond_handle(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
828 tvbparse_wanted_t* w = *(wanted->control.handle);
829 int len = w->condition(tt, offset, w, tok);
838 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
839 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
841 w->condition = cond_handle;
842 w->control.handle = handle;
847 static int cond_end(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
848 if (offset == tt->end_offset) {
849 *tok = new_tok(tt,wanted->id,offset,0,wanted);
856 tvbparse_wanted_t* tvbparse_end_of_buffer(int id,
858 tvbparse_action_t before_cb,
859 tvbparse_action_t after_cb) {
860 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
863 w->condition = cond_end;
865 w->before = before_cb;
873 /* these extract binary values */
875 static int cond_ft(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
878 if ( offset + wanted->len > tt->end_offset )
883 } else if (wanted->control.ftenum == FT_STRINGZ) {
884 if (( len = tvb_find_guint8(tt->tvb,offset,tt->end_offset - offset,'\0') >= 0 )) {
885 *tok = new_tok(tt,wanted->id,offset,len,wanted);
895 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 };
897 tvbparse_wanted_t* tvbparse_ft(int id,
899 tvbparse_action_t before_cb,
900 tvbparse_action_t after_cb,
901 enum ftenum ftenum) {
902 gint len = ft_lens[ftenum];
905 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
908 w->condition = cond_ft;
910 w->control.ftenum = ftenum;
912 w->before = before_cb;
917 g_assert(! "unsupported ftenum" );
922 static int cond_ft_comp(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
923 void* l = wanted->control.number.extract(tt->tvb,offset);
924 const void* r = &(wanted->control.number.value);
926 if ( offset + wanted->len > tt->end_offset )
929 if ( wanted->control.number.comp(&l,&r) ) {
930 *tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
937 static gboolean comp_gt_i(void* lp, const void* rp) { return ( *((gint64*)lp) > *((gint64*)rp) ); }
938 static gboolean comp_ge_i(void* lp, const void* rp) { return ( *((gint64*)lp) >= *((gint64*)rp) ); }
939 static gboolean comp_eq_i(void* lp, const void* rp) { return ( *((gint64*)lp) == *((gint64*)rp) ); }
940 static gboolean comp_ne_i(void* lp, const void* rp) { return ( *((gint64*)lp) != *((gint64*)rp) ); }
941 static gboolean comp_le_i(void* lp, const void* rp) { return ( *((gint64*)lp) <= *((gint64*)rp) ); }
942 static gboolean comp_lt_i(void* lp, const void* rp) { return ( *((gint64*)lp) < *((gint64*)rp) ); }
944 static gboolean comp_gt_u(void* lp, const void* rp) { return ( *((guint64*)lp) > *((guint64*)rp) ); }
945 static gboolean comp_ge_u(void* lp, const void* rp) { return ( *((guint64*)lp) >= *((guint64*)rp) ); }
946 static gboolean comp_eq_u(void* lp, const void* rp) { return ( *((guint64*)lp) == *((guint64*)rp) ); }
947 static gboolean comp_ne_u(void* lp, const void* rp) { return ( *((guint64*)lp) != *((guint64*)rp) ); }
948 static gboolean comp_le_u(void* lp, const void* rp) { return ( *((guint64*)lp) <= *((guint64*)rp) ); }
949 static gboolean comp_lt_u(void* lp, const void* rp) { return ( *((guint64*)lp) < *((guint64*)rp) ); }
951 static gboolean comp_gt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) > *((gdouble*)rp) ); }
952 static gboolean comp_ge_f(void* lp, const void* rp) { return ( *((gdouble*)lp) >= *((gdouble*)rp) ); }
953 static gboolean comp_eq_f(void* lp, const void* rp) { return ( *((gdouble*)lp) == *((gdouble*)rp) ); }
954 static gboolean comp_ne_f(void* lp, const void* rp) { return ( *((gdouble*)lp) != *((gdouble*)rp) ); }
955 static gboolean comp_le_f(void* lp, const void* rp) { return ( *((gdouble*)lp) <= *((gdouble*)rp) ); }
956 static gboolean comp_lt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) < *((gdouble*)rp) ); }
958 static void* extract_u8(tvbuff_t* tvb, guint offset) {
959 guint64* p = ep_new(guint64);
960 *p = tvb_get_guint8(tvb,offset);
964 static void* extract_uns(tvbuff_t* tvb, guint offset) {
965 guint64* p = ep_new(guint64);
966 *p = tvb_get_ntohs(tvb,offset);
970 static void* extract_un24(tvbuff_t* tvb, guint offset) {
971 guint64* p = ep_new(guint64);
972 *p = tvb_get_ntoh24(tvb,offset);
976 static void* extract_unl(tvbuff_t* tvb, guint offset) {
977 guint64* p = ep_new(guint64);
978 *p = tvb_get_ntohl(tvb,offset);
982 static void* extract_un64(tvbuff_t* tvb, guint offset) {
983 guint64* p = ep_new(guint64);
984 *p = tvb_get_ntoh64(tvb,offset);
988 static void* extract_ules(tvbuff_t* tvb, guint offset) {
989 guint64* p = ep_new(guint64);
990 *p = tvb_get_letohs(tvb,offset);
994 static void* extract_ule24(tvbuff_t* tvb, guint offset) {
995 guint64* p = ep_new(guint64);
996 *p = tvb_get_letoh24(tvb,offset);
1000 static void* extract_ulel(tvbuff_t* tvb, guint offset) {
1001 guint64* p = ep_new(guint64);
1002 *p = tvb_get_letohl(tvb,offset);
1006 static void* extract_ule64(tvbuff_t* tvb, guint offset) {
1007 guint64* p = ep_new(guint64);
1008 *p = tvb_get_letoh64(tvb,offset);
1012 static void* extract_ins(tvbuff_t* tvb, guint offset) {
1013 guint64* p = ep_new(guint64);
1014 *p = tvb_get_ntohs(tvb,offset);
1018 static void* extract_in24(tvbuff_t* tvb, guint offset) {
1019 guint64* p = ep_new(guint64);
1020 *p = tvb_get_ntoh24(tvb,offset);
1024 static void* extract_inl(tvbuff_t* tvb, guint offset) {
1025 guint64* p = ep_new(guint64);
1026 *p = tvb_get_ntohl(tvb,offset);
1030 static void* extract_in64(tvbuff_t* tvb, guint offset) {
1031 guint64* p = ep_new(guint64);
1032 *p = tvb_get_ntoh64(tvb,offset);
1036 static void* extract_iles(tvbuff_t* tvb, guint offset) {
1037 guint64* p = ep_new(guint64);
1038 *p = tvb_get_letohs(tvb,offset);
1042 static void* extract_ile24(tvbuff_t* tvb, guint offset) {
1043 guint64* p = ep_new(guint64);
1044 *p = tvb_get_letoh24(tvb,offset);
1048 static void* extract_ilel(tvbuff_t* tvb, guint offset) {
1049 guint64* p = ep_new(guint64);
1050 *p = tvb_get_letohl(tvb,offset);
1054 static void* extract_ile64(tvbuff_t* tvb, guint offset) {
1055 guint64* p = ep_new(guint64);
1056 *p = tvb_get_letoh64(tvb,offset);
1060 static void* extract_inf(tvbuff_t* tvb, guint offset) {
1061 gdouble* p = ep_new(gdouble);
1062 *p = tvb_get_ntohieee_float(tvb,offset);
1066 static void* extract_ind(tvbuff_t* tvb, guint offset) {
1067 gdouble* p = ep_new(gdouble);
1068 *p = tvb_get_ntohieee_double(tvb,offset);
1072 static void* extract_ilef(tvbuff_t* tvb, guint offset) {
1073 gdouble* p = ep_new(gdouble);
1074 *p = tvb_get_letohieee_float(tvb,offset);
1078 static void* extract_iled(tvbuff_t* tvb, guint offset) {
1079 gdouble* p = ep_new(gdouble);
1080 *p = tvb_get_letohieee_double(tvb,offset);
1086 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};
1087 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};
1088 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};
1090 static gboolean (**comps[])(void*, const void*) = {comps_u,comps_i,comps_f};
1092 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 };
1093 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 };
1095 static void* (**extracts[])(tvbuff_t* tvb, guint offset) = { extract_n, extract_le};
1098 tvbparse_wanted_t* tvbparse_ft_numcmp(int id,
1100 tvbparse_action_t before_cb,
1101 tvbparse_action_t after_cb,
1104 enum ft_cmp_op ft_cmp_op,
1106 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
1109 va_start(ap,ft_cmp_op);
1116 w->control.number.comp = comps[0][ft_cmp_op];
1117 w->control.number.value.u = va_arg(ap,guint32);
1120 w->control.number.comp = comps[0][ft_cmp_op];
1121 w->control.number.value.u = va_arg(ap,guint64);
1127 w->control.number.comp = comps[1][ft_cmp_op];
1128 w->control.number.value.i = va_arg(ap,gint32);
1131 w->control.number.comp = comps[1][ft_cmp_op];
1132 w->control.number.value.i = va_arg(ap,gint64);
1136 w->control.number.comp = comps[1][ft_cmp_op];
1137 w->control.number.value.i = va_arg(ap,gdouble);
1140 g_assert(! "comparision unsupported");
1143 w->control.number.extract = extracts[little_endian][ftenum];
1145 g_assert(w->control.number.extract && "extraction unsupported");
1148 w->condition = cond_ft_comp;
1149 w->after = after_cb;
1150 w->before = before_cb;
1159 tvbparse_wanted_t* tvbparse_quoted(int id,
1161 tvbparse_action_t before_cb,
1162 tvbparse_action_t after_cb,
1166 gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
1167 gchar* quot = g_strdup_printf("%c",quote);
1168 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
1170 return tvbparse_set_oneof(id, data, before_cb, after_cb,
1171 tvbparse_set_seq(-1, NULL, NULL, NULL,
1173 tvbparse_set_seq(-1,NULL,NULL,NULL,
1174 tvbparse_set_oneof(-1, NULL, NULL, NULL,
1175 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
1176 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
1181 tvbparse_set_seq(-1, NULL, NULL, NULL,
1188 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
1189 const void* wanted_data _U_,
1190 tvbparse_elem_t* tok) {
1195 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
1199 const tvbparse_wanted_t* ignore) {
1200 tvbparse_t* tt = ep_alloc(sizeof(tvbparse_t));
1202 #ifdef TVBPARSE_DEBUG
1203 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1208 tt->offset = offset;
1209 len = (len == -1) ? (int) tvb_length(tvb) : len;
1210 tt->end_offset = offset + len;
1212 tt->ignore = ignore;
1216 gboolean tvbparse_reset(tvbparse_t* tt,
1220 #ifdef TVBPARSE_DEBUG
1221 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1224 len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
1226 if( tvb_length_remaining(tt->tvb, offset) >= len) {
1227 tt->offset = offset;
1228 tt->end_offset = offset + len;
1235 guint tvbparse_curr_offset(tvbparse_t* tt) {
1239 static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
1240 ep_stack_t stack = ep_stack_new();
1243 if(curr->wanted->before) {
1244 #ifdef TVBPARSE_DEBUG
1245 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1247 curr->wanted->before(tt->data, curr->wanted->data, curr);
1251 ep_stack_push(stack,curr);
1255 #ifdef TVBPARSE_DEBUG
1256 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1258 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
1263 while( !curr && ep_stack_peek(stack) ) {
1264 curr = ep_stack_pop(stack);
1265 #ifdef TVBPARSE_DEBUG
1266 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1268 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
1275 gboolean tvbparse_peek(tvbparse_t* tt,
1276 const tvbparse_wanted_t* wanted) {
1277 tvbparse_elem_t* tok = NULL;
1279 int offset = tt->offset;
1281 #ifdef TVBPARSE_DEBUG
1282 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: ENTER offset=%i",offset);
1285 offset += ignore(tt,offset);
1287 #ifdef TVBPARSE_DEBUG
1288 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: after ignore offset=%i",offset);
1291 consumed = wanted->condition(tt,offset,wanted,&tok);
1293 if (consumed >= 0) {
1294 #ifdef TVBPARSE_DEBUG
1295 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: GOT len=%i",consumed);
1299 #ifdef TVBPARSE_DEBUG
1300 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: NOT GOT");
1307 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
1308 const tvbparse_wanted_t* wanted) {
1309 tvbparse_elem_t* tok = NULL;
1311 int offset = tt->offset;
1313 #ifdef TVBPARSE_DEBUG
1314 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: ENTER offset=%i",offset);
1317 offset += ignore(tt,offset);
1319 #ifdef TVBPARSE_DEBUG
1320 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: after ignore offset=%i",offset);
1323 consumed = wanted->condition(tt,offset,wanted,&tok);
1325 if (consumed >= 0) {
1326 #ifdef TVBPARSE_DEBUG
1327 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: GOT len=%i",consumed);
1329 execute_callbacks(tt,tok);
1330 tt->offset = offset + consumed;
1331 #ifdef TVBPARSE_DEBUG
1332 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1342 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
1343 tvbparse_elem_t* tok = NULL;
1345 int offset = tt->offset;
1346 int target_offset = offset -1;
1348 #ifdef TVBPARSE_DEBUG
1349 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: ENTER offset=%i", tt->offset);
1353 len = wanted->condition(tt, target_offset+1, wanted, &tok);
1354 } while(len < 0 && ++target_offset < tt->end_offset);
1357 #ifdef TVBPARSE_DEBUG
1358 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len);
1360 execute_callbacks(tt,tok);
1361 tt->offset = target_offset + len;
1363 #ifdef TVBPARSE_DEBUG
1364 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1368 #ifdef TVBPARSE_DEBUG
1369 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: NOT FOUND");
1375 struct _elem_tree_stack_frame {
1377 tvbparse_elem_t* elem;
1380 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
1381 ep_stack_t stack = ep_stack_new();
1382 struct _elem_tree_stack_frame* frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
1388 pi = proto_tree_add_text(frame->tree,curr->tvb,curr->offset,curr->len,"%s",tvb_format_text(curr->tvb,curr->offset,curr->len));
1392 ep_stack_push(stack,frame);
1393 frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
1394 frame->tree = proto_item_add_subtree(pi,0);
1401 while( !curr && ep_stack_peek(stack) ) {
1402 frame = ep_stack_pop(stack);
1403 curr = frame->elem->next;