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 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/wmem/wmem.h>
31 #include <epan/proto.h>
32 #include <epan/packet_info.h>
33 #include <epan/tvbparse.h>
34 #include <wsutil/ws_printf.h> /* ws_g_warning */
37 #define TVBPARSE_DEBUG_ALL 0xffffffff
40 #define TVBPARSE_DEBUG_ 0x80000000
41 #define TVBPARSE_DEBUG_ 0x40000000
42 #define TVBPARSE_DEBUG_ 0x20000000
43 #define TVBPARSE_DEBUG_ 0x10000000
46 #define TVBPARSE_DEBUG_CHAR 0x08000000
47 #define TVBPARSE_DEBUG_CHARS 0x04000000
48 #define TVBPARSE_DEBUG_NOT_CHAR 0x02000000
49 #define TVBPARSE_DEBUG_NOT_CHARS 0x01000000
50 #define TVBPARSE_DEBUG_STRING 0x00800000
51 #define TVBPARSE_DEBUG_CASESTRING 0x00400000
52 #define TVBPARSE_DEBUG_ONEOF 0x00200000
53 #define TVBPARSE_DEBUG_HASH 0x00100000
54 #define TVBPARSE_DEBUG_SEQ 0x00080000
55 #define TVBPARSE_DEBUG_SOME 0x00040000
56 #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
72 #define TVBPARSE_DEBUG_ 0x00000010
73 #define TVBPARSE_DEBUG_ 0x00000008
74 #define TVBPARSE_DEBUG_ 0x00000004
75 #define TVBPARSE_DEBUG_ 0x00000002
76 #define TVBPARSE_DEBUG_ 0x00000001
80 #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
83 #define TVBPARSE_MAX_RECURSION_DEPTH 100 // Arbitrary. Matches DAAP and PNIO.
85 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
89 const tvbparse_wanted_t* wanted) {
93 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) ws_g_warning("new_tok: id=%i offset=%u len=%u",id,offset,len);
96 tok = (tvbparse_elem_t *)wmem_new(wmem_packet_scope(), tvbparse_elem_t);
100 tok->offset = offset;
105 tok->wanted = wanted;
111 static int ignore_fcn(tvbparse_t* tt, int offset) {
114 tvbparse_elem_t* ignored = NULL;
116 if (!tt->ignore) return 0;
118 #ifdef TVBPARSE_DEBUG
119 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_g_warning("ignore: enter");
122 while ((consumed = tt->ignore->condition(tt,offset,tt->ignore,&ignored)) > 0) {
125 #ifdef TVBPARSE_DEBUG
126 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_g_warning("ignore: consumed=%i",consumed);
131 #ifdef TVBPARSE_DEBUG
132 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_g_warning("ignore: len=%i",len);
139 static int cond_char (tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
143 #ifdef TVBPARSE_DEBUG
144 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) ws_g_warning("cond_char: control='%s'",wanted->control.str);
147 if ( offset + 1 > tt->end_offset )
150 t = (gchar) tvb_get_guint8(tt->tvb,offset);
152 for(i = 0; (c = wanted->control.str[i]) && offset <= tt->end_offset; i++) {
154 *tok = new_tok(tt,wanted->id,offset,1,wanted);
155 #ifdef TVBPARSE_DEBUG
156 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) ws_g_warning("cond_char: GOT: '%c'",c);
165 tvbparse_wanted_t* tvbparse_char(const int id,
168 tvbparse_action_t before_cb,
169 tvbparse_action_t after_cb) {
170 tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t);
172 w->condition = cond_char;
174 w->control.str = chr;
177 w->before = before_cb;
183 static int cond_chars_common(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
186 int left = tt->end_offset - offset;
188 #ifdef TVBPARSE_DEBUG
189 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) ws_g_warning("cond_chars_common: control='%s'",wanted->control.str);
192 if ( offset + (int)wanted->min > tt->end_offset )
195 left = left < (int) wanted->max ? left : (int) wanted->max;
198 guint8 t = tvb_get_guint8(tt->tvb,offset++);
200 if (!wanted->control.str[t])
207 if (length < wanted->min) {
210 *tok = new_tok(tt,wanted->id,start,length,wanted);
211 #ifdef TVBPARSE_DEBUG
212 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) ws_g_warning("cond_chars_common: GOT len=%i",length);
218 tvbparse_wanted_t* tvbparse_chars(const int id,
223 tvbparse_action_t before_cb,
224 tvbparse_action_t after_cb)
226 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
230 accept_str = (char *)wmem_alloc(wmem_epan_scope(), 256);
231 memset(accept_str, 0x00, 256);
232 for (i = 0; chr[i]; i++)
233 accept_str[(unsigned)chr[i]] = (char)0xFF;
235 w->condition = cond_chars_common;
237 w->control.str = accept_str;
238 w->min = min_len ? min_len : 1;
239 w->max = max_len ? max_len : G_MAXINT/2;
241 w->before = before_cb;
248 static int cond_not_char(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
251 gboolean not_matched = FALSE;
253 #ifdef TVBPARSE_DEBUG
254 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) ws_g_warning("cond_not_char: control='%s'",wanted->control.str);
257 if ( offset >= tt->end_offset ) {
261 t = (gchar) tvb_get_guint8(tt->tvb,offset);
263 for(i = 0; (c = wanted->control.str[i]); i++) {
272 *tok = new_tok(tt,wanted->id,offset,1,wanted);
273 #ifdef TVBPARSE_DEBUG
274 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) ws_g_warning("cond_not_char: GOT='%c'",t);
280 tvbparse_wanted_t* tvbparse_not_char(const int id,
283 tvbparse_action_t before_cb,
284 tvbparse_action_t after_cb) {
285 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
287 w->condition = cond_not_char;
289 w->control.str = chr;
291 w->before = before_cb;
297 tvbparse_wanted_t* tvbparse_not_chars(const int id,
302 tvbparse_action_t before_cb,
303 tvbparse_action_t after_cb)
305 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
309 /* cond_chars_common() use accept string, so mark all elements with, and later unset from reject */
310 accept_str = (char *)wmem_alloc(wmem_epan_scope(), 256);
311 memset(accept_str, 0xFF, 256);
312 for (i = 0; chr[i]; i++)
313 accept_str[(unsigned) chr[i]] = '\0';
315 w->condition = cond_chars_common;
317 w->control.str = accept_str;
319 w->min = min_len ? min_len : 1;
320 w->max = max_len ? max_len : G_MAXINT/2;
322 w->before = before_cb;
329 static int cond_string(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
330 int len = wanted->len;
331 #ifdef TVBPARSE_DEBUG
332 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) ws_g_warning("cond_string: control='%s'",wanted->control.str);
335 if ( offset + wanted->len > tt->end_offset )
338 if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
339 *tok = new_tok(tt,wanted->id,offset,len,wanted);
340 #ifdef TVBPARSE_DEBUG
341 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) ws_g_warning("cond_string: GOT len=%i",len);
349 tvbparse_wanted_t* tvbparse_string(const int id,
352 tvbparse_action_t before_cb,
353 tvbparse_action_t after_cb) {
354 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
356 w->condition = cond_string;
358 w->control.str = str;
359 w->len = (int) strlen(str);
361 w->before = before_cb;
367 static int cond_casestring(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
368 int len = wanted->len;
369 #ifdef TVBPARSE_DEBUG
370 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) ws_g_warning("cond_casestring: control='%s'",wanted->control.str);
373 if ( offset + len > tt->end_offset )
376 if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
377 *tok = new_tok(tt,wanted->id,offset,len,wanted);
378 #ifdef TVBPARSE_DEBUG
379 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) ws_g_warning("cond_casestring: GOT len=%i",len);
388 tvbparse_wanted_t* tvbparse_casestring(const int id,
391 tvbparse_action_t before_cb,
392 tvbparse_action_t after_cb) {
393 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
395 w->condition = cond_casestring;
397 w->control.str = str;
398 w->len = (int) strlen(str);
400 w->before = before_cb;
406 static int cond_one_of(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
408 #ifdef TVBPARSE_DEBUG
409 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) ws_g_warning("cond_one_of: START");
412 if ( offset > tt->end_offset )
415 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
418 for(i=0; i < wanted->control.elems->len; i++) {
419 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i);
420 tvbparse_elem_t* new_elem = NULL;
423 if ( offset + w->len > tt->end_offset )
426 curr_len = w->condition(tt, offset, w, &new_elem);
429 *tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
430 (*tok)->sub = new_elem;
431 #ifdef TVBPARSE_DEBUG
432 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) ws_g_warning("cond_one_of: GOT len=%i",curr_len);
434 tt->recursion_depth--;
439 tt->recursion_depth--;
444 tvbparse_wanted_cleanup_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data)
446 tvbparse_wanted_t* w = (tvbparse_wanted_t *)user_data;
447 g_ptr_array_free(w->control.elems, TRUE);
451 tvbparse_wanted_t* tvbparse_set_oneof(const int id,
453 tvbparse_action_t before_cb,
454 tvbparse_action_t after_cb,
456 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
460 w->condition = cond_one_of;
463 w->before = before_cb;
465 w->control.elems = g_ptr_array_new();
466 wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb, w);
468 va_start(ap,after_cb);
470 while(( el = va_arg(ap,tvbparse_t*) )) {
471 g_ptr_array_add(w->control.elems,el);
479 static int cond_hash(tvbparse_t* tt, const int offset, const tvbparse_wanted_t* wanted, tvbparse_elem_t** tok) {
482 tvbparse_elem_t* key_elem = NULL;
483 tvbparse_wanted_t* value_wanted = NULL;
485 tvbparse_elem_t* value_elem = NULL;
487 tvbparse_elem_t* ret_tok;
489 #ifdef TVBPARSE_DEBUG
490 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_g_warning("cond_hash: START");
493 if ( offset > tt->end_offset )
496 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
499 key_len = wanted->control.hash.key->condition(tt, offset, wanted->control.hash.key, &key_elem);
502 tt->recursion_depth--;
506 key = tvb_get_string_enc(wmem_packet_scope(),key_elem->tvb,key_elem->offset,key_elem->len, ENC_ASCII);
507 #ifdef TVBPARSE_DEBUG
508 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_g_warning("cond_hash: got key='%s'",key);
511 if ((value_wanted = (tvbparse_wanted_t *)wmem_map_lookup(wanted->control.hash.table,key))) {
512 value_len = value_wanted->condition(tt, offset + key_len, value_wanted, &value_elem);
513 } else if (wanted->control.hash.other) {
514 value_len = wanted->control.hash.other->condition(tt, offset+key_len, wanted->control.hash.other, &value_elem);
516 tt->recursion_depth--;
520 tt->recursion_depth--;
524 tt->recursion_depth--;
526 tot_len = key_len + value_len;
528 ret_tok = new_tok(tt, value_elem->id, offset, tot_len, wanted);
529 ret_tok->sub = key_elem;
530 ret_tok->sub->last->next = value_elem;
533 #ifdef TVBPARSE_DEBUG
534 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_g_warning("cond_hash: GOT len=%i",tot_len);
540 tvbparse_wanted_t* tvbparse_hashed(const int id,
542 tvbparse_action_t before_cb,
543 tvbparse_action_t after_cb,
544 tvbparse_wanted_t* key,
545 tvbparse_wanted_t* other,
547 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
549 tvbparse_wanted_t* el;
552 w->condition = cond_hash;
555 w->before = before_cb;
557 w->control.hash.table = wmem_map_new(wmem_epan_scope(), g_str_hash,g_str_equal);
558 w->control.hash.key = key;
559 w->control.hash.other = other;
563 while(( name = va_arg(ap,gchar*) )) {
564 el = va_arg(ap,tvbparse_wanted_t*);
565 wmem_map_insert(w->control.hash.table,name,el);
573 void tvbparse_hashed_add(tvbparse_wanted_t* w, ...) {
574 tvbparse_wanted_t* el;
580 while (( name = va_arg(ap,gchar*) )) {
581 el = va_arg(ap,tvbparse_wanted_t*);
582 wmem_map_insert(w->control.hash.table,name,el);
588 static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
592 tvbparse_elem_t* ret_tok = NULL;
594 #ifdef TVBPARSE_DEBUG
595 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) ws_g_warning("cond_seq: START");
598 if ( offset > tt->end_offset )
601 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
604 for(i=0; i < wanted->control.elems->len; i++) {
605 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i);
606 tvbparse_elem_t* new_elem = NULL;
608 if ( offset + w->len > tt->end_offset ) {
609 tt->recursion_depth--;
613 len = w->condition(tt, offset, w, &new_elem);
618 ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
619 ret_tok->sub->last->next = new_elem;
620 ret_tok->sub->last = new_elem;
622 ret_tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
623 ret_tok->sub = new_elem;
624 new_elem->last = new_elem;
627 tt->recursion_depth--;
632 offset += ignore_fcn(tt,offset);
635 tt->recursion_depth--;
639 #ifdef TVBPARSE_DEBUG
640 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) ws_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 = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), 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();
662 wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb, w);
664 va_start(ap,after_cb);
666 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
667 g_ptr_array_add(w->control.elems,el);
674 static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
675 guint got_so_far = 0;
677 tvbparse_elem_t* ret_tok = NULL;
678 #ifdef TVBPARSE_DEBUG
679 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_g_warning("cond_some: START");
682 if ( offset > tt->end_offset )
685 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
688 if ( wanted->min == 0 ) {
689 ret_tok = new_tok(tt,wanted->id,offset,0,wanted);
692 while (got_so_far < wanted->max) {
693 tvbparse_elem_t* new_elem = NULL;
696 if ( offset > tt->end_offset ) {
697 tt->recursion_depth--;
701 consumed = wanted->control.subelem->condition(tt, offset, wanted->control.subelem, &new_elem);
706 ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
709 ret_tok->sub->last->next = new_elem;
710 ret_tok->sub->last = new_elem;
712 ret_tok->sub = new_elem;
715 ret_tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
716 ret_tok->sub = new_elem;
726 tt->recursion_depth--;
728 #ifdef TVBPARSE_DEBUG
729 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_g_warning("cond_some: got num=%u",got_so_far);
732 if(got_so_far < wanted->min) {
737 #ifdef TVBPARSE_DEBUG
738 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_g_warning("cond_some: GOT len=%i",offset - start);
740 return offset - start;
743 tvbparse_wanted_t* tvbparse_some(const int id,
747 tvbparse_action_t before_cb,
748 tvbparse_action_t after_cb,
749 const tvbparse_wanted_t* el) {
751 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
753 g_assert(from <= to);
755 w->condition = cond_some;
760 w->before = before_cb;
762 w->control.subelem = el;
768 static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
769 tvbparse_elem_t* new_elem = NULL;
771 int target_offset = offset;
772 #ifdef TVBPARSE_DEBUG
773 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_g_warning("cond_until: START");
776 if ( offset + wanted->control.until.subelem->len > tt->end_offset )
779 if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH)
783 len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem, &new_elem);
784 } while(len < 0 && target_offset+1 < tt->end_offset);
786 tt->recursion_depth--;
790 new_elem->id = wanted->id;
791 new_elem->next = NULL;
792 new_elem->last = NULL;
793 new_elem->wanted = wanted;
794 new_elem->offset = offset;
798 switch (wanted->control.until.mode) {
799 case TP_UNTIL_INCLUDE:
800 new_elem->len = target_offset - offset - 1 + len;
801 #ifdef TVBPARSE_DEBUG
802 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
804 return target_offset - offset -1 + len;
806 new_elem->len = target_offset - offset - 1;
807 #ifdef TVBPARSE_DEBUG
808 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
810 return target_offset - offset - 1 + len;
812 new_elem->len = target_offset - offset - 1;
813 #ifdef TVBPARSE_DEBUG
814 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_g_warning("cond_until: GOT len=%i",target_offset - offset -1);
816 return target_offset - offset -1;
818 DISSECTOR_ASSERT_NOT_REACHED();
827 tvbparse_wanted_t* tvbparse_until(const int id,
829 tvbparse_action_t before_cb,
830 tvbparse_action_t after_cb,
831 const tvbparse_wanted_t* el,
832 until_mode_t until_mode) {
833 tvbparse_wanted_t* w = (tvbparse_wanted_t *)wmem_alloc0(wmem_epan_scope(), sizeof(tvbparse_wanted_t));
835 w->condition = cond_until;
836 w->control.until.mode = until_mode;
837 w->control.until.subelem = el;
840 w->before = before_cb;
847 static int cond_handle(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
848 tvbparse_wanted_t* w = *(wanted->control.handle);
849 int len = w->condition(tt, offset, w, tok);
858 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
859 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
861 w->condition = cond_handle;
862 w->control.handle = handle;
867 static int cond_end(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
868 if (offset == tt->end_offset) {
869 *tok = new_tok(tt,wanted->id,offset,0,wanted);
876 tvbparse_wanted_t* tvbparse_end_of_buffer(const int id,
878 tvbparse_action_t before_cb,
879 tvbparse_action_t after_cb) {
880 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
883 w->condition = cond_end;
885 w->before = before_cb;
892 /* these extract binary values */
894 static int cond_ft(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
897 if ( offset + wanted->len > tt->end_offset )
902 } else if (wanted->control.ftenum == FT_STRINGZ) {
903 if (( len = tvb_find_guint8(tt->tvb,offset,tt->end_offset - offset,'\0') >= 0 )) {
904 *tok = new_tok(tt,wanted->id,offset,len,wanted);
914 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 };
916 tvbparse_wanted_t* tvbparse_ft(int id,
918 tvbparse_action_t before_cb,
919 tvbparse_action_t after_cb,
920 enum ftenum ftenum) {
921 gint len = ft_lens[ftenum];
924 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
927 w->condition = cond_ft;
929 w->control.ftenum = ftenum;
931 w->before = before_cb;
936 g_assert(! "unsupported ftenum" );
941 static int cond_ft_comp(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
942 void* l = wanted->control.number.extract(tt->tvb,offset);
943 const void* r = &(wanted->control.number.value);
945 if ( offset + wanted->len > tt->end_offset )
948 if ( wanted->control.number.comp(&l,&r) ) {
949 *tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
956 static gboolean comp_gt_i(void* lp, const void* rp) { return ( *((gint64*)lp) > *((gint64*)rp) ); }
957 static gboolean comp_ge_i(void* lp, const void* rp) { return ( *((gint64*)lp) >= *((gint64*)rp) ); }
958 static gboolean comp_eq_i(void* lp, const void* rp) { return ( *((gint64*)lp) == *((gint64*)rp) ); }
959 static gboolean comp_ne_i(void* lp, const void* rp) { return ( *((gint64*)lp) != *((gint64*)rp) ); }
960 static gboolean comp_le_i(void* lp, const void* rp) { return ( *((gint64*)lp) <= *((gint64*)rp) ); }
961 static gboolean comp_lt_i(void* lp, const void* rp) { return ( *((gint64*)lp) < *((gint64*)rp) ); }
963 static gboolean comp_gt_u(void* lp, const void* rp) { return ( *((guint64*)lp) > *((guint64*)rp) ); }
964 static gboolean comp_ge_u(void* lp, const void* rp) { return ( *((guint64*)lp) >= *((guint64*)rp) ); }
965 static gboolean comp_eq_u(void* lp, const void* rp) { return ( *((guint64*)lp) == *((guint64*)rp) ); }
966 static gboolean comp_ne_u(void* lp, const void* rp) { return ( *((guint64*)lp) != *((guint64*)rp) ); }
967 static gboolean comp_le_u(void* lp, const void* rp) { return ( *((guint64*)lp) <= *((guint64*)rp) ); }
968 static gboolean comp_lt_u(void* lp, const void* rp) { return ( *((guint64*)lp) < *((guint64*)rp) ); }
970 static gboolean comp_gt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) > *((gdouble*)rp) ); }
971 static gboolean comp_ge_f(void* lp, const void* rp) { return ( *((gdouble*)lp) >= *((gdouble*)rp) ); }
972 static gboolean comp_eq_f(void* lp, const void* rp) { return ( *((gdouble*)lp) == *((gdouble*)rp) ); }
973 static gboolean comp_ne_f(void* lp, const void* rp) { return ( *((gdouble*)lp) != *((gdouble*)rp) ); }
974 static gboolean comp_le_f(void* lp, const void* rp) { return ( *((gdouble*)lp) <= *((gdouble*)rp) ); }
975 static gboolean comp_lt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) < *((gdouble*)rp) ); }
977 static void* extract_u8(tvbuff_t* tvb, guint offset) {
978 guint64* p = wmem_new(wmem_packet_scope(), guint64);
979 *p = tvb_get_guint8(tvb,offset);
983 static void* extract_uns(tvbuff_t* tvb, guint offset) {
984 guint64* p = wmem_new(wmem_packet_scope(), guint64);
985 *p = tvb_get_ntohs(tvb,offset);
989 static void* extract_un24(tvbuff_t* tvb, guint offset) {
990 guint64* p = wmem_new(wmem_packet_scope(), guint64);
991 *p = tvb_get_ntoh24(tvb,offset);
995 static void* extract_unl(tvbuff_t* tvb, guint offset) {
996 guint64* p = wmem_new(wmem_packet_scope(), guint64);
997 *p = tvb_get_ntohl(tvb,offset);
1001 static void* extract_un64(tvbuff_t* tvb, guint offset) {
1002 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1003 *p = tvb_get_ntoh64(tvb,offset);
1007 static void* extract_ules(tvbuff_t* tvb, guint offset) {
1008 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1009 *p = tvb_get_letohs(tvb,offset);
1013 static void* extract_ule24(tvbuff_t* tvb, guint offset) {
1014 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1015 *p = tvb_get_letoh24(tvb,offset);
1019 static void* extract_ulel(tvbuff_t* tvb, guint offset) {
1020 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1021 *p = tvb_get_letohl(tvb,offset);
1025 static void* extract_ule64(tvbuff_t* tvb, guint offset) {
1026 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1027 *p = tvb_get_letoh64(tvb,offset);
1031 static void* extract_ins(tvbuff_t* tvb, guint offset) {
1032 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1033 *p = tvb_get_ntohs(tvb,offset);
1037 static void* extract_in24(tvbuff_t* tvb, guint offset) {
1038 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1039 *p = tvb_get_ntoh24(tvb,offset);
1043 static void* extract_inl(tvbuff_t* tvb, guint offset) {
1044 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1045 *p = tvb_get_ntohl(tvb,offset);
1049 static void* extract_in64(tvbuff_t* tvb, guint offset) {
1050 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1051 *p = tvb_get_ntoh64(tvb,offset);
1055 static void* extract_iles(tvbuff_t* tvb, guint offset) {
1056 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1057 *p = tvb_get_letohs(tvb,offset);
1061 static void* extract_ile24(tvbuff_t* tvb, guint offset) {
1062 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1063 *p = tvb_get_letoh24(tvb,offset);
1067 static void* extract_ilel(tvbuff_t* tvb, guint offset) {
1068 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1069 *p = tvb_get_letohl(tvb,offset);
1073 static void* extract_ile64(tvbuff_t* tvb, guint offset) {
1074 guint64* p = wmem_new(wmem_packet_scope(), guint64);
1075 *p = tvb_get_letoh64(tvb,offset);
1079 static void* extract_inf(tvbuff_t* tvb, guint offset) {
1080 gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
1081 *p = tvb_get_ntohieee_float(tvb,offset);
1085 static void* extract_ind(tvbuff_t* tvb, guint offset) {
1086 gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
1087 *p = tvb_get_ntohieee_double(tvb,offset);
1091 static void* extract_ilef(tvbuff_t* tvb, guint offset) {
1092 gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
1093 *p = tvb_get_letohieee_float(tvb,offset);
1097 static void* extract_iled(tvbuff_t* tvb, guint offset) {
1098 gdouble* p = wmem_new(wmem_packet_scope(), gdouble);
1099 *p = tvb_get_letohieee_double(tvb,offset);
1105 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};
1106 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};
1107 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};
1109 static gboolean (**comps[])(void*, const void*) = {comps_u,comps_i,comps_f};
1111 static void* (*extract_n[])(tvbuff_t* tvb, guint offset) = {
1112 NULL, NULL, NULL, extract_u8, extract_uns, extract_un24, extract_unl,
1113 extract_un64, extract_u8, extract_ins, extract_in24, extract_inl,
1114 extract_in64, extract_inf, extract_ind, NULL, NULL, NULL, NULL, NULL, NULL,
1115 NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL
1117 static void* (*extract_le[])(tvbuff_t* tvb, guint offset) = {
1118 NULL, NULL, NULL, extract_u8, extract_ules, extract_ule24, extract_ulel,
1119 extract_ule64, extract_u8, extract_iles, extract_ile24, extract_ilel,
1120 extract_ile64, extract_ilef, extract_iled, NULL, NULL, NULL, NULL, NULL,
1121 NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL
1124 static void* (**extracts[])(tvbuff_t* tvb, guint offset) = { extract_n, extract_le};
1127 tvbparse_wanted_t* tvbparse_ft_numcmp(int id,
1129 tvbparse_action_t before_cb,
1130 tvbparse_action_t after_cb,
1133 enum ft_cmp_op ft_cmp_op,
1135 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
1138 va_start(ap,ft_cmp_op);
1145 w->control.number.comp = comps[0][ft_cmp_op];
1146 w->control.number.value.u = va_arg(ap,guint32);
1149 w->control.number.comp = comps[0][ft_cmp_op];
1150 w->control.number.value.u = va_arg(ap,guint64);
1156 w->control.number.comp = comps[1][ft_cmp_op];
1157 w->control.number.value.i = va_arg(ap,gint32);
1160 w->control.number.comp = comps[1][ft_cmp_op];
1161 w->control.number.value.i = va_arg(ap,gint64);
1165 w->control.number.comp = comps[1][ft_cmp_op];
1166 w->control.number.value.i = va_arg(ap,gdouble);
1169 g_assert(! "comparison unsupported");
1172 w->control.number.extract = extracts[little_endian][ftenum];
1174 g_assert(w->control.number.extract && "extraction unsupported");
1177 w->condition = cond_ft_comp;
1178 w->after = after_cb;
1179 w->before = before_cb;
1188 tvbparse_wanted_t* tvbparse_quoted(const int id,
1190 tvbparse_action_t before_cb,
1191 tvbparse_action_t after_cb,
1195 gchar* esc_quot = wmem_strdup_printf(wmem_epan_scope(), "%c%c",esc,quote);
1196 gchar* quot = wmem_strdup_printf(wmem_epan_scope(), "%c",quote);
1197 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
1199 return tvbparse_set_oneof(id, data, before_cb, after_cb,
1200 tvbparse_set_seq(-1, NULL, NULL, NULL,
1202 tvbparse_set_seq(-1,NULL,NULL,NULL,
1203 tvbparse_set_oneof(-1, NULL, NULL, NULL,
1204 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
1205 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
1210 tvbparse_set_seq(-1, NULL, NULL, NULL,
1217 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
1218 const void* wanted_data _U_,
1219 tvbparse_elem_t* tok) {
1224 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
1228 const tvbparse_wanted_t* ignore) {
1229 tvbparse_t* tt = (tvbparse_t *)wmem_new(wmem_packet_scope(), tvbparse_t);
1231 #ifdef TVBPARSE_DEBUG
1232 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) ws_g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1237 tt->offset = offset;
1238 len = (len == -1) ? (int) tvb_captured_length(tvb) : len;
1239 tt->end_offset = offset + len;
1241 tt->ignore = ignore;
1242 tt->recursion_depth = 0;
1246 gboolean tvbparse_reset(tvbparse_t* tt,
1250 #ifdef TVBPARSE_DEBUG
1251 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) ws_g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1254 len = (len == -1) ? (int) tvb_captured_length(tt->tvb) : len;
1256 if( tvb_captured_length_remaining(tt->tvb, offset) >= len) {
1257 tt->offset = offset;
1258 tt->end_offset = offset + len;
1265 guint tvbparse_curr_offset(tvbparse_t* tt) {
1269 static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
1270 wmem_stack_t *stack = wmem_stack_new(wmem_packet_scope());
1273 if(curr->wanted->before) {
1274 #ifdef TVBPARSE_DEBUG
1275 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1277 curr->wanted->before(tt->data, curr->wanted->data, curr);
1281 wmem_stack_push(stack, curr);
1285 #ifdef TVBPARSE_DEBUG
1286 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1288 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
1293 while( !curr && wmem_stack_count(stack) > 0 ) {
1294 curr = (tvbparse_elem_t *)wmem_stack_pop(stack);
1295 #ifdef TVBPARSE_DEBUG
1296 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1298 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
1305 gboolean tvbparse_peek(tvbparse_t* tt,
1306 const tvbparse_wanted_t* wanted) {
1307 tvbparse_elem_t* tok = NULL;
1309 int offset = tt->offset;
1311 #ifdef TVBPARSE_DEBUG
1312 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_g_warning("tvbparse_peek: ENTER offset=%i",offset);
1315 offset += ignore_fcn(tt,offset);
1317 #ifdef TVBPARSE_DEBUG
1318 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_g_warning("tvbparse_peek: after ignore offset=%i",offset);
1321 consumed = wanted->condition(tt,offset,wanted,&tok);
1323 if (consumed >= 0) {
1324 #ifdef TVBPARSE_DEBUG
1325 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_g_warning("tvbparse_peek: GOT len=%i",consumed);
1329 #ifdef TVBPARSE_DEBUG
1330 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_g_warning("tvbparse_peek: NOT GOT");
1337 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
1338 const tvbparse_wanted_t* wanted) {
1339 tvbparse_elem_t* tok = NULL;
1341 int offset = tt->offset;
1343 #ifdef TVBPARSE_DEBUG
1344 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_g_warning("tvbparse_get: ENTER offset=%i",offset);
1347 offset += ignore_fcn(tt,offset);
1349 #ifdef TVBPARSE_DEBUG
1350 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_g_warning("tvbparse_get: after ignore offset=%i",offset);
1353 consumed = wanted->condition(tt,offset,wanted,&tok);
1355 if (consumed >= 0) {
1356 #ifdef TVBPARSE_DEBUG
1357 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_g_warning("tvbparse_get: GOT len=%i",consumed);
1359 execute_callbacks(tt,tok);
1360 tt->offset = offset + consumed;
1361 #ifdef TVBPARSE_DEBUG
1362 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1372 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
1373 tvbparse_elem_t* tok = NULL;
1375 int offset = tt->offset;
1376 int target_offset = offset -1;
1378 #ifdef TVBPARSE_DEBUG
1379 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_g_warning("tvbparse_get: ENTER offset=%i", tt->offset);
1383 len = wanted->condition(tt, target_offset+1, wanted, &tok);
1384 } while(len < 0 && ++target_offset < tt->end_offset);
1387 #ifdef TVBPARSE_DEBUG
1388 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len);
1390 execute_callbacks(tt,tok);
1391 tt->offset = target_offset + len;
1393 #ifdef TVBPARSE_DEBUG
1394 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1398 #ifdef TVBPARSE_DEBUG
1399 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_g_warning("tvbparse_get: NOT FOUND");
1405 struct _elem_tree_stack_frame {
1407 tvbparse_elem_t* elem;
1410 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
1411 wmem_stack_t *stack = wmem_stack_new(wmem_packet_scope());
1412 struct _elem_tree_stack_frame* frame = wmem_new(wmem_packet_scope(), struct _elem_tree_stack_frame);
1418 pi = proto_tree_add_format_text(frame->tree,curr->tvb,curr->offset,curr->len);
1422 wmem_stack_push(stack, frame);
1423 frame = wmem_new(wmem_packet_scope(), struct _elem_tree_stack_frame);
1424 frame->tree = proto_item_add_subtree(pi,0);
1431 while( !curr && wmem_stack_count(stack) > 0 ) {
1432 frame = (struct _elem_tree_stack_frame *)wmem_stack_pop(stack);
1433 curr = frame->elem->next;
1440 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1445 * indent-tabs-mode: nil
1448 * vi: set shiftwidth=4 tabstop=8 expandtab:
1449 * :indentSize=4:tabSize=8:noTabs=true: