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/tvbparse.h>
38 typedef enum _tvbparse_wanted_type_t {
39 TVBPARSE_WANTED_NONE, /* currently unused */
42 TVBPARSE_WANTED_SIMPLE_CHAR, /* just one matching char */
43 TVBPARSE_WANTED_SIMPLE_CHARS, /* a sequence of matching chars */
44 TVBPARSE_WANTED_SIMPLE_NOT_CHAR, /* one non matching char */
45 TVBPARSE_WANTED_SIMPLE_NOT_CHARS, /* a sequence of non matching chars */
46 TVBPARSE_WANTED_SIMPLE_STRING, /* a string */
47 TVBPARSE_WANTED_SIMPLE_CASESTRING, /* a caseless string */
48 TVBPARSE_WANTED_UNTIL, /* all the characters until the first matching token */
51 TVBPARSE_WANTED_SET_ONEOF, /* one of the given types */
52 TVBPARSE_WANTED_SET_SEQ, /* an exact sequence of tokens of the given types */
53 TVBPARSE_WANTED_CARDINALITY, /* one or more tokens of the given type */
54 TVBPARSE_WANTED_HANDLE, /* a handle to another one */
63 const tvbparse_wanted_t* ignore;
67 struct _tvbparse_wanted_t {
74 struct _tvbparse_wanted_t** handle;
83 tvbparse_action_t before;
84 tvbparse_action_t after;
90 tvbparse_wanted_t* tvbparse_char(int id,
93 tvbparse_action_t before_cb,
94 tvbparse_action_t after_cb) {
95 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
98 w->type = TVBPARSE_WANTED_SIMPLE_CHAR;
104 w->before = before_cb;
106 w->elems = g_ptr_array_new();
111 tvbparse_wanted_t* tvbparse_chars(int id,
116 tvbparse_action_t before_cb,
117 tvbparse_action_t after_cb) {
118 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
121 w->type = TVBPARSE_WANTED_SIMPLE_CHARS;
122 w->control.str = chr;
124 w->min = min_len ? min_len : 1;
125 w->max = max_len ? max_len : G_MAXINT;
127 w->before = before_cb;
129 w->elems = g_ptr_array_new();
134 tvbparse_wanted_t* tvbparse_not_char(int id,
137 tvbparse_action_t before_cb,
138 tvbparse_action_t after_cb) {
139 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
142 w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHAR;
143 w->control.str = chr;
148 w->before = before_cb;
150 w->elems = g_ptr_array_new();
155 tvbparse_wanted_t* tvbparse_not_chars(int id,
160 tvbparse_action_t before_cb,
161 tvbparse_action_t after_cb){
162 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
165 w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHARS;
166 w->control.str = chr;
168 w->min = min_len ? min_len : 1;
169 w->max = max_len ? max_len : G_MAXINT;
171 w->before = before_cb;
173 w->elems = g_ptr_array_new();
179 tvbparse_wanted_t* tvbparse_string(int id,
182 tvbparse_action_t before_cb,
183 tvbparse_action_t after_cb) {
184 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
187 w->type = TVBPARSE_WANTED_SIMPLE_STRING;
188 w->control.str = str;
189 w->len = strlen(str);
193 w->before = before_cb;
195 w->elems = g_ptr_array_new();
200 tvbparse_wanted_t* tvbparse_casestring(int id,
203 tvbparse_action_t before_cb,
204 tvbparse_action_t after_cb) {
205 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
208 w->type = TVBPARSE_WANTED_SIMPLE_CASESTRING;
209 w->control.str = str;
210 w->len = strlen(str);
214 w->before = before_cb;
216 w->elems = g_ptr_array_new();
222 tvbparse_wanted_t* tvbparse_set_oneof(int id,
224 tvbparse_action_t before_cb,
225 tvbparse_action_t after_cb,
227 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
232 w->type = TVBPARSE_WANTED_SET_ONEOF;
238 w->before = before_cb;
240 w->elems = g_ptr_array_new();
242 va_start(ap,after_cb);
244 while(( el = va_arg(ap,tvbparse_t*) )) {
245 g_ptr_array_add(w->elems,el);
253 tvbparse_wanted_t* tvbparse_set_seq(int id,
255 tvbparse_action_t before_cb,
256 tvbparse_action_t after_cb,
258 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
259 tvbparse_wanted_t* el = NULL;
263 w->type = TVBPARSE_WANTED_SET_SEQ;
269 w->before = before_cb;
271 w->elems = g_ptr_array_new();
273 va_start(ap,after_cb);
275 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
276 g_ptr_array_add(w->elems,el);
284 tvbparse_wanted_t* tvbparse_some(int id,
288 tvbparse_action_t before_cb,
289 tvbparse_action_t after_cb,
290 const tvbparse_wanted_t* el) {
292 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
294 g_assert(from <= to);
297 w->type = TVBPARSE_WANTED_CARDINALITY;
303 w->before = before_cb;
305 w->elems = g_ptr_array_new();
307 g_ptr_array_add(w->elems,(gpointer)el);
312 tvbparse_wanted_t* tvbparse_until(int id,
314 tvbparse_action_t before_cb,
315 tvbparse_action_t after_cb,
316 const tvbparse_wanted_t* el,
318 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
321 w->type = TVBPARSE_WANTED_UNTIL;
323 w->control.val = op_mode;
329 w->before = before_cb;
331 w->elems = g_ptr_array_new();
333 g_ptr_array_add(w->elems,(gpointer)el);
338 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
339 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
342 w->type = TVBPARSE_WANTED_HANDLE;
344 w->control.handle = handle;
358 tvbparse_wanted_t* tvbparse_quoted(int id,
360 tvbparse_action_t before_cb,
361 tvbparse_action_t after_cb,
365 gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
366 gchar* quot = g_strdup_printf("%c",quote);
367 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
369 return tvbparse_set_oneof(id, data, before_cb, after_cb,
370 tvbparse_set_seq(-1, NULL, NULL, NULL,
372 tvbparse_set_seq(-1,NULL,NULL,NULL,
373 tvbparse_set_oneof(-1, NULL, NULL, NULL,
374 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
375 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
380 tvbparse_set_seq(-1, NULL, NULL, NULL,
388 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
389 const void* wanted_data _U_,
390 tvbparse_elem_t* tok) {
395 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
399 const tvbparse_wanted_t* ignore) {
400 tvbparse_t* tt = ep_alloc(sizeof(tvbparse_t));
404 tt->max_len = (len == -1) ? (int) tvb_length(tvb) : len;
411 gboolean tvbparse_reset(tvbparse_t* tt,
415 len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
417 if( tvb_length_remaining(tt->tvb, offset) >= len) {
428 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
432 const tvbparse_wanted_t* wanted) {
433 tvbparse_elem_t* tok = ep_alloc(sizeof(tvbparse_elem_t));
437 tok->offset = offset;
442 tok->wanted = wanted;
448 guint tvbparse_curr_offset(tvbparse_t* tt) {
451 guint tvbparse_len_left(tvbparse_t* tt) {
455 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
456 const tvbparse_wanted_t* wanted) {
457 tvbparse_elem_t* tok = NULL;
458 int save_offset = tt->offset;
459 int save_len = tt->max_len;
463 if (tt->ignore && tt->ignore != wanted) {
464 tvbparse_wanted_t* save = (void*)tt->ignore;
466 while ( tvbparse_get(tt,save) ) {
472 switch(wanted->type) {
473 case TVBPARSE_WANTED_NONE:
475 case TVBPARSE_WANTED_SIMPLE_NOT_CHAR:
479 gboolean not_matched = FALSE;
484 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
486 for(i = 0; (c = wanted->control.str[i]) && tt->max_len; i++) {
497 tok = new_tok(tt,wanted->id,tt->offset-1,1,wanted);
501 case TVBPARSE_WANTED_SIMPLE_CHAR:
509 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
511 for(i = 0; (c = wanted->control.str[i]) && tt->max_len; i++) {
515 tok = new_tok(tt,wanted->id,tt->offset-1,1,wanted);
521 case TVBPARSE_WANTED_SIMPLE_NOT_CHARS:
525 guint offset = tt->offset;
528 while( tt->max_len && length < wanted->max) {
529 gboolean not_matched = FALSE;
530 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
533 while ( (c = wanted->control.str[i]) && tt->max_len ) {
550 if ( length < wanted->min ) {
553 tok = new_tok(tt,wanted->id,offset,length,wanted);
557 case TVBPARSE_WANTED_SIMPLE_CHARS:
561 guint offset = tt->offset;
564 while( tt->max_len && length < wanted->max) {
565 gboolean matched = FALSE;
566 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
569 while ( (c = wanted->control.str[i]) && tt->max_len ) {
587 if (length < wanted->min) {
590 tok = new_tok(tt,wanted->id,offset,length,wanted);
594 case TVBPARSE_WANTED_SIMPLE_STRING:
596 if ( tvb_strneql(tt->tvb, tt->offset, wanted->control.str, wanted->len) == 0 ) {
597 int offset = tt->offset;
598 tt->offset += wanted->len;
599 tt->max_len -= wanted->len;
600 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
606 case TVBPARSE_WANTED_SIMPLE_CASESTRING:
608 if ( tvb_strncaseeql(tt->tvb, tt->offset, wanted->control.str, wanted->len) == 0 ) {
609 int offset = tt->offset;
610 tt->offset += wanted->len;
611 tt->max_len -= wanted->len;
612 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
618 case TVBPARSE_WANTED_SET_ONEOF:
622 for(i=0; i < wanted->elems->len; i++) {
623 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
624 tvbparse_elem_t* new = tvbparse_get(tt, w);
627 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
634 case TVBPARSE_WANTED_SET_SEQ:
638 for(i=0; i < wanted->elems->len; i++) {
639 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
640 tvbparse_elem_t* new = tvbparse_get(tt, w);
644 tok->len = (new->offset - tok->offset) + new->len;
645 tok->sub->last->next = new;
646 tok->sub->last = new;
648 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
659 case TVBPARSE_WANTED_CARDINALITY:
661 guint got_so_far = 0;
662 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
664 if ( wanted->min == 0 ) {
665 new_tok(tt,wanted->id,tt->offset,0,wanted);
668 while (got_so_far < wanted->max) {
669 tvbparse_elem_t* new = tvbparse_get(tt, w);
673 tok->len = (new->offset - tok->offset) + new->len;
674 tok->sub->last->next = new;
675 tok->sub->last = new;
677 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
687 if(got_so_far < wanted->min) {
693 case TVBPARSE_WANTED_UNTIL:
695 int offset = tt->offset;
696 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
697 tvbparse_elem_t* new = tvbparse_find(tt, w);
702 switch (wanted->control.val) {
703 case TP_UNTIL_INCLUDE:
704 tok->len = (tok->offset - offset) + tok->len;
707 tt->offset -= tok->len;
708 tt->max_len += tok->len;
711 tok->len = (tok->offset - offset);
714 DISSECTOR_ASSERT_NOT_REACHED();
717 tok->offset = offset;
718 tok->id = wanted->id;
721 tok->wanted = wanted;
728 case TVBPARSE_WANTED_HANDLE:
730 tok = tvbparse_get(tt, *(wanted->control.handle));
739 DISSECTOR_ASSERT_NOT_REACHED();
744 if( tt->depth == 1 ) {
745 GPtrArray* stack = g_ptr_array_new();
746 tvbparse_elem_t* curr = tok;
750 if(curr->wanted->before) {
751 curr->wanted->before(tt->data, curr->wanted->data, curr);
755 g_ptr_array_add(stack,curr);
759 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
764 while( !curr && stack->len ) {
765 curr = g_ptr_array_remove_index_fast(stack,stack->len - 1);
766 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
772 g_ptr_array_free(stack,TRUE);
780 tt->offset = save_offset;
781 tt->max_len = save_len;
788 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
789 int save_offset = tt->offset;
790 int save_len = tt->max_len;
791 tvbparse_elem_t* tok = NULL;
793 while ( tvb_length_remaining(tt->tvb,tt->offset) >= wanted->len ) {
794 if (( tok = tvbparse_get(tt, wanted) )) {
801 tt->offset = save_offset;
802 tt->max_len = save_len;
808 static void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
809 GPtrArray* stack = g_ptr_array_new();
810 struct _elem_tree_stack_frame* frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
816 pi = proto_tree_add_text(frame->tree,curr->tvb,curr->offset,curr->len,"%s",tvb_format_text(curr->tvb,curr->offset,curr->len));
820 g_ptr_array_add(stack,frame);
821 frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
822 frame->tree = proto_item_add_subtree(pi,0);
829 while( !curr && stack->len ) {
830 frame = g_ptr_array_remove_index_fast(stack,stack->len - 1);
831 curr = frame->elem->next;
836 g_ptr_array_free(stack,TRUE);