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>
39 typedef enum _tvbparse_wanted_type_t {
40 TVBPARSE_WANTED_NONE, /* currently unused */
43 TVBPARSE_WANTED_SIMPLE_CHAR, /* just one matching char */
44 TVBPARSE_WANTED_SIMPLE_CHARS, /* a sequence of matching chars */
45 TVBPARSE_WANTED_SIMPLE_NOT_CHAR, /* one non matching char */
46 TVBPARSE_WANTED_SIMPLE_NOT_CHARS, /* a sequence of non matching chars */
47 TVBPARSE_WANTED_SIMPLE_STRING, /* a string */
48 TVBPARSE_WANTED_SIMPLE_CASESTRING, /* a caseless string */
49 TVBPARSE_WANTED_UNTIL, /* all the characters until the first matching token */
52 TVBPARSE_WANTED_SET_ONEOF, /* one of the given types */
53 TVBPARSE_WANTED_SET_SEQ, /* an exact sequence of tokens of the given types */
54 TVBPARSE_WANTED_CARDINALITY, /* one or more tokens of the given type */
55 TVBPARSE_WANTED_HANDLE, /* a handle to another one */
64 const tvbparse_wanted_t* ignore;
68 struct _tvbparse_wanted_t {
75 struct _tvbparse_wanted_t** handle;
84 tvbparse_action_t before;
85 tvbparse_action_t after;
91 tvbparse_wanted_t* tvbparse_char(int id,
94 tvbparse_action_t before_cb,
95 tvbparse_action_t after_cb) {
96 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
99 w->type = TVBPARSE_WANTED_SIMPLE_CHAR;
100 w->control.str = chr;
105 w->before = before_cb;
107 w->elems = g_ptr_array_new();
112 tvbparse_wanted_t* tvbparse_chars(int id,
117 tvbparse_action_t before_cb,
118 tvbparse_action_t after_cb) {
119 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
122 w->type = TVBPARSE_WANTED_SIMPLE_CHARS;
123 w->control.str = chr;
125 w->min = min_len ? min_len : 1;
126 w->max = max_len ? max_len : G_MAXINT;
128 w->before = before_cb;
130 w->elems = g_ptr_array_new();
135 tvbparse_wanted_t* tvbparse_not_char(int id,
138 tvbparse_action_t before_cb,
139 tvbparse_action_t after_cb) {
140 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
143 w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHAR;
144 w->control.str = chr;
149 w->before = before_cb;
151 w->elems = g_ptr_array_new();
156 tvbparse_wanted_t* tvbparse_not_chars(int id,
161 tvbparse_action_t before_cb,
162 tvbparse_action_t after_cb){
163 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
166 w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHARS;
167 w->control.str = chr;
169 w->min = min_len ? min_len : 1;
170 w->max = max_len ? max_len : G_MAXINT;
172 w->before = before_cb;
174 w->elems = g_ptr_array_new();
180 tvbparse_wanted_t* tvbparse_string(int id,
183 tvbparse_action_t before_cb,
184 tvbparse_action_t after_cb) {
185 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
188 w->type = TVBPARSE_WANTED_SIMPLE_STRING;
189 w->control.str = str;
190 w->len = strlen(str);
194 w->before = before_cb;
196 w->elems = g_ptr_array_new();
201 tvbparse_wanted_t* tvbparse_casestring(int id,
204 tvbparse_action_t before_cb,
205 tvbparse_action_t after_cb) {
206 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
209 w->type = TVBPARSE_WANTED_SIMPLE_CASESTRING;
210 w->control.str = str;
211 w->len = strlen(str);
215 w->before = before_cb;
217 w->elems = g_ptr_array_new();
223 tvbparse_wanted_t* tvbparse_set_oneof(int id,
225 tvbparse_action_t before_cb,
226 tvbparse_action_t after_cb,
228 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
233 w->type = TVBPARSE_WANTED_SET_ONEOF;
239 w->before = before_cb;
241 w->elems = g_ptr_array_new();
243 va_start(ap,after_cb);
245 while(( el = va_arg(ap,tvbparse_t*) )) {
246 g_ptr_array_add(w->elems,el);
254 tvbparse_wanted_t* tvbparse_set_seq(int id,
256 tvbparse_action_t before_cb,
257 tvbparse_action_t after_cb,
259 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
260 tvbparse_wanted_t* el = NULL;
264 w->type = TVBPARSE_WANTED_SET_SEQ;
270 w->before = before_cb;
272 w->elems = g_ptr_array_new();
274 va_start(ap,after_cb);
276 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
277 g_ptr_array_add(w->elems,el);
285 tvbparse_wanted_t* tvbparse_some(int id,
289 tvbparse_action_t before_cb,
290 tvbparse_action_t after_cb,
291 const tvbparse_wanted_t* el) {
293 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
295 g_assert(from <= to);
298 w->type = TVBPARSE_WANTED_CARDINALITY;
304 w->before = before_cb;
306 w->elems = g_ptr_array_new();
308 g_ptr_array_add(w->elems,(gpointer)el);
313 tvbparse_wanted_t* tvbparse_until(int id,
315 tvbparse_action_t before_cb,
316 tvbparse_action_t after_cb,
317 const tvbparse_wanted_t* el,
319 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
322 w->type = TVBPARSE_WANTED_UNTIL;
324 w->control.val = op_mode;
330 w->before = before_cb;
332 w->elems = g_ptr_array_new();
334 g_ptr_array_add(w->elems,(gpointer)el);
339 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
340 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
343 w->type = TVBPARSE_WANTED_HANDLE;
345 w->control.handle = handle;
359 tvbparse_wanted_t* tvbparse_quoted(int id,
361 tvbparse_action_t before_cb,
362 tvbparse_action_t after_cb,
366 gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
367 gchar* quot = g_strdup_printf("%c",quote);
368 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
370 return tvbparse_set_oneof(id, data, before_cb, after_cb,
371 tvbparse_set_seq(-1, NULL, NULL, NULL,
373 tvbparse_set_seq(-1,NULL,NULL,NULL,
374 tvbparse_set_oneof(-1, NULL, NULL, NULL,
375 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
376 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
381 tvbparse_set_seq(-1, NULL, NULL, NULL,
389 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
390 const void* wanted_data _U_,
391 tvbparse_elem_t* tok) {
396 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
400 const tvbparse_wanted_t* ignore) {
401 tvbparse_t* tt = ep_alloc(sizeof(tvbparse_t));
405 tt->max_len = (len == -1) ? (int) tvb_length(tvb) : len;
412 gboolean tvbparse_reset(tvbparse_t* tt,
416 len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
418 if( tvb_length_remaining(tt->tvb, offset) >= len) {
429 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
433 const tvbparse_wanted_t* wanted) {
434 tvbparse_elem_t* tok = ep_alloc(sizeof(tvbparse_elem_t));
438 tok->offset = offset;
443 tok->wanted = wanted;
449 guint tvbparse_curr_offset(tvbparse_t* tt) {
452 guint tvbparse_len_left(tvbparse_t* tt) {
456 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
457 const tvbparse_wanted_t* wanted) {
458 tvbparse_elem_t* tok = NULL;
459 int save_offset = tt->offset;
460 int save_len = tt->max_len;
464 if (tt->ignore && tt->ignore != wanted) {
465 tvbparse_wanted_t* save = (void*)tt->ignore;
467 while ( tvbparse_get(tt,save) ) {
473 switch(wanted->type) {
474 case TVBPARSE_WANTED_NONE:
476 case TVBPARSE_WANTED_SIMPLE_NOT_CHAR:
480 gboolean not_matched = FALSE;
485 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
487 for(i = 0; (c = wanted->control.str[i]) && tt->max_len; i++) {
498 tok = new_tok(tt,wanted->id,tt->offset-1,1,wanted);
502 case TVBPARSE_WANTED_SIMPLE_CHAR:
510 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
512 for(i = 0; (c = wanted->control.str[i]) && tt->max_len; i++) {
516 tok = new_tok(tt,wanted->id,tt->offset-1,1,wanted);
522 case TVBPARSE_WANTED_SIMPLE_NOT_CHARS:
526 guint offset = tt->offset;
529 while( tt->max_len && length < wanted->max) {
530 gboolean not_matched = FALSE;
531 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
534 while ( (c = wanted->control.str[i]) && tt->max_len ) {
551 if ( length < wanted->min ) {
554 tok = new_tok(tt,wanted->id,offset,length,wanted);
558 case TVBPARSE_WANTED_SIMPLE_CHARS:
562 guint offset = tt->offset;
565 while( tt->max_len && length < wanted->max) {
566 gboolean matched = FALSE;
567 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
570 while ( (c = wanted->control.str[i]) && tt->max_len ) {
588 if (length < wanted->min) {
591 tok = new_tok(tt,wanted->id,offset,length,wanted);
595 case TVBPARSE_WANTED_SIMPLE_STRING:
597 if ( tvb_strneql(tt->tvb, tt->offset, wanted->control.str, wanted->len) == 0 ) {
598 int offset = tt->offset;
599 tt->offset += wanted->len;
600 tt->max_len -= wanted->len;
601 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
607 case TVBPARSE_WANTED_SIMPLE_CASESTRING:
609 if ( tvb_strncaseeql(tt->tvb, tt->offset, wanted->control.str, wanted->len) == 0 ) {
610 int offset = tt->offset;
611 tt->offset += wanted->len;
612 tt->max_len -= wanted->len;
613 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
619 case TVBPARSE_WANTED_SET_ONEOF:
623 for(i=0; i < wanted->elems->len; i++) {
624 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
625 tvbparse_elem_t* new = tvbparse_get(tt, w);
628 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
635 case TVBPARSE_WANTED_SET_SEQ:
639 for(i=0; i < wanted->elems->len; i++) {
640 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
641 tvbparse_elem_t* new = tvbparse_get(tt, w);
645 tok->len = (new->offset - tok->offset) + new->len;
646 tok->sub->last->next = new;
647 tok->sub->last = new;
649 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
660 case TVBPARSE_WANTED_CARDINALITY:
662 guint got_so_far = 0;
663 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
665 if ( wanted->min == 0 ) {
666 new_tok(tt,wanted->id,tt->offset,0,wanted);
669 while (got_so_far < wanted->max) {
670 tvbparse_elem_t* new = tvbparse_get(tt, w);
674 tok->len = (new->offset - tok->offset) + new->len;
675 tok->sub->last->next = new;
676 tok->sub->last = new;
678 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
688 if(got_so_far < wanted->min) {
694 case TVBPARSE_WANTED_UNTIL:
696 int offset = tt->offset;
697 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
698 tvbparse_elem_t* new = tvbparse_find(tt, w);
703 switch (wanted->control.val) {
704 case TP_UNTIL_INCLUDE:
705 tok->len = (tok->offset - offset) + tok->len;
708 tt->offset -= tok->len;
709 tt->max_len += tok->len;
712 tok->len = (tok->offset - offset);
715 DISSECTOR_ASSERT_NOT_REACHED();
718 tok->offset = offset;
719 tok->id = wanted->id;
722 tok->wanted = wanted;
729 case TVBPARSE_WANTED_HANDLE:
731 tok = tvbparse_get(tt, *(wanted->control.handle));
740 DISSECTOR_ASSERT_NOT_REACHED();
745 if( tt->depth == 1 ) {
746 GPtrArray* stack = g_ptr_array_new();
747 tvbparse_elem_t* curr = tok;
751 if(curr->wanted->before) {
752 curr->wanted->before(tt->data, curr->wanted->data, curr);
756 g_ptr_array_add(stack,curr);
760 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
765 while( !curr && stack->len ) {
766 curr = g_ptr_array_remove_index_fast(stack,stack->len - 1);
767 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
773 g_ptr_array_free(stack,TRUE);
781 tt->offset = save_offset;
782 tt->max_len = save_len;
789 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
790 int save_offset = tt->offset;
791 int save_len = tt->max_len;
792 tvbparse_elem_t* tok = NULL;
794 while ( tvb_length_remaining(tt->tvb,tt->offset) >= wanted->len ) {
795 if (( tok = tvbparse_get(tt, wanted) )) {
802 tt->offset = save_offset;
803 tt->max_len = save_len;
808 struct _elem_tree_stack_frame {
810 tvbparse_elem_t* elem;
813 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
814 GPtrArray* stack = g_ptr_array_new();
815 struct _elem_tree_stack_frame* frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
821 pi = proto_tree_add_text(frame->tree,curr->tvb,curr->offset,curr->len,"%s",tvb_format_text(curr->tvb,curr->offset,curr->len));
825 g_ptr_array_add(stack,frame);
826 frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
827 frame->tree = proto_item_add_subtree(pi,0);
834 while( !curr && stack->len ) {
835 frame = g_ptr_array_remove_index_fast(stack,stack->len - 1);
836 curr = frame->elem->next;
841 g_ptr_array_free(stack,TRUE);