7030dc409867f9f443c4d892c773080f8faf2eb7
[obnox/wireshark/wip.git] / epan / tvbparse.h
1
2 /* tvbparse.h
3 *
4 * an API for text tvb parsers
5 *
6 * Copyright 2005, Luis E. Garcia Ontanon <luis@ontanon.org>
7 *
8 * $Id$
9 *
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 * GNU General Public License for more details.
23
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 /*
30  The intention behind this is to ease the writing of dissectors that have to
31  parse text without the need of writing into buffers.
32  
33  It was originally written to avoid using lex and yacc for the xml dissector.
34  
35  the parser is able to look for wanted elements these can be:
36  
37  simple tokens:
38  - a char out of a string of needles
39  - a char not belonging to a string of needles
40  - a sequence of chars that belong to a set of chars
41  - a sequence of chars that do not belong to a set of chars
42  - a string
43  - a caseless string
44  - all the characters up to a certain wanted element (included or excluded)
45  
46  composed elements:
47  - one of a given group of wanted elements
48  - a sequence of wanted elements
49  - some (at least one) instances of a wanted element
50  
51  Once a wanted element is successfully extracted, by either tvbparse_get or
52  tvbparse_find, the parser will invoke a given callback 
53  before and another one after every of its component's subelement's callbacks
54  are being called.
55  
56  If tvbparse_get or tvbparse_find fail to extract the wanted element the
57  subelements callbacks are not going to be invoked.
58  
59  The wanted elements are instantiated once by the proto_register_xxx function.
60  
61  The parser is instantiated for every packet and it mantains its state.
62  
63  The element's data is destroyed before the next packet is dissected.
64  */
65
66 #ifndef _TVB_PARSE_H_
67 #define _TVB_PARSE_H_
68
69 #include <epan/tvbuff.h>
70 #include <glib.h>
71
72 typedef struct _tvbparse_elem_t tvbparse_elem_t;
73 typedef struct _tvbparse_wanted_t tvbparse_wanted_t;
74 typedef struct _tvbparse_t tvbparse_t;
75
76
77 /*
78  * a callback function to be called before or after an element has been
79  * successfuly extracted.
80  *
81  * Note that if the token belongs to a composed token the callbacks of the
82  * components won't be called unless the composed token is successfully
83  * extracted.
84  *
85  * tvbparse_data: the private data of the parser
86  * wanted_data: the private data of the wanted element
87  * elem: the extracted element
88  */
89 typedef void (*tvbparse_action_t)(void* tvbparse_data, const void* wanted_data, struct _tvbparse_elem_t* elem);
90
91 typedef int (*tvbparse_condition_t)
92 (tvbparse_t*, const int,
93  const tvbparse_wanted_t*, 
94  tvbparse_elem_t**);
95
96
97 typedef enum  {
98     TP_UNTIL_INCLUDE, /* last elem is included, its span is spent by the parser */
99     TP_UNTIL_SPEND, /* last elem is not included, but its span is spent by the parser */
100     TP_UNTIL_LEAVE /* last elem is not included, neither its span is spent by the parser */
101 } until_mode_t;
102
103
104 struct _tvbparse_wanted_t {
105         int id;
106     tvbparse_condition_t condition;
107     
108         union {
109         const gchar* str;
110         struct _tvbparse_wanted_t** handle;
111         struct {
112             union {
113                 gint64 i;
114                 guint64 u;
115                 gdouble f;
116             } value;            
117             gboolean (*comp)(void*,const void*);
118             void* (*extract)(tvbuff_t*,guint);
119         } number;
120         enum ftenum ftenum;
121         struct {
122             until_mode_t mode;
123             const tvbparse_wanted_t* subelem;
124         } until;
125         struct {
126             GHashTable* table;
127             struct _tvbparse_wanted_t* key;
128             struct _tvbparse_wanted_t* other;
129         } hash;
130         GPtrArray* elems;
131         const tvbparse_wanted_t* subelem;
132         void* p;
133     } control;
134     
135         int len;
136         
137         guint min;
138         guint max;
139         
140         const void* data;
141     
142         tvbparse_action_t before;
143         tvbparse_action_t after;
144         
145 };
146
147 /* an instance of a per packet parser */
148 struct _tvbparse_t {
149         tvbuff_t* tvb;
150         int offset;
151     int end_offset;
152         void* data;
153         const tvbparse_wanted_t* ignore;
154 };
155
156
157 /* a matching token returned by either tvbparser_get or tvb_parser_find */
158 struct _tvbparse_elem_t {
159         int id;
160         
161         tvbuff_t* tvb;
162         int offset;
163         int len;
164         
165         void* data;
166         
167         struct _tvbparse_elem_t* sub;
168         
169         struct _tvbparse_elem_t* next;
170         struct _tvbparse_elem_t* last;
171         
172         const tvbparse_wanted_t* wanted;
173 };
174
175
176 /*
177  * definition of wanted token types
178  *
179  * the following functions define the tokens we will be able to look for in a tvb
180  * common parameters are:
181  *
182  * id: an arbitrary id that will be copied to the eventual token (don't use 0)
183  * private_data: persistent data to be passed to the callback action (wanted_data)
184  * before_cb: an callback function to be called before those of the subelements
185  * after_cb: an callback function to be called after those of the subelements
186  */
187
188
189 /*
190  * a char element.
191  *
192  * When looked for it returns a simple element one character long if the char
193  * at the current offset matches one of the the needles.
194  */
195 tvbparse_wanted_t* tvbparse_char(const int id,
196                                                                  const gchar* needles,
197                                                                  const void* private_data,
198                                                                  tvbparse_action_t before_cb,
199                                                                  tvbparse_action_t after_cb);
200
201 /*
202  * a not_char element.
203  *
204  * When looked for it returns a simple element one character long if the char
205  * at the current offset does not match one of the the needles.
206  */
207 tvbparse_wanted_t* tvbparse_not_char(const int id,
208                                                                          const gchar* needle,
209                                                                          const void* private_data,
210                                                                          tvbparse_action_t before_cb,
211                                                                          tvbparse_action_t after_cb);
212
213 /*
214  * a chars element
215  *
216  * When looked for it returns a simple element one or more characters long if
217  * one or more char(s) starting from the current offset match one of the needles.
218  * An element will be returned if at least min_len chars are given (1 if it's 0) 
219  * It will get at most max_len chars or as much as it can if max_len is 0.
220  */
221 tvbparse_wanted_t* tvbparse_chars(const int id,
222                                                                   const guint min_len,
223                                                                   const guint max_len,
224                                                                   const gchar* needles,
225                                                                   const void* private_data,
226                                                                   tvbparse_action_t before_cb,
227                                                                   tvbparse_action_t after_cb);
228
229 /*
230  * a not_chars element
231  *
232  * When looked for it returns a simple element one or more characters long if
233  * one or more char(s) starting from the current offset do not match one of the
234  * needles.
235  * An element will be returned if at least min_len chars are given (1 if it's 0) 
236  * It will get at most max_len chars or as much as it can if max_len is 0.
237  */
238 tvbparse_wanted_t* tvbparse_not_chars(const int id,
239                                                                           const guint min_len,
240                                                                           const guint max_len,
241                                                                           const gchar* needles,
242                                                                           const void* private_data,
243                                                                           tvbparse_action_t before_cb,
244                                                                           tvbparse_action_t after_cb);
245
246 /*
247  * a string element
248  *
249  * When looked for it returns a simple element if we have the given string at
250  * the current offset 
251  */
252 tvbparse_wanted_t* tvbparse_string(const int id,
253                                                                    const gchar* string,
254                                                                    const void* private_data,
255                                                                    tvbparse_action_t before_cb,
256                                                                    tvbparse_action_t after_cb);
257
258 /*
259  * casestring
260  *
261  * When looked for it returns a simple element if we have a matching string at
262  * the current offset 
263  */
264 tvbparse_wanted_t* tvbparse_casestring(const int id,
265                                                                            const gchar* str,
266                                                                            const void* data,
267                                                                            tvbparse_action_t before_cb,
268                                                                            tvbparse_action_t after_cb);
269
270 /*
271  * until
272  *
273  * When looked for it returns a simple element containing all the characters 
274  * found until the first match of the ending element if the ending element is
275  * found.
276  *
277  * When looking for until elements it calls tvbparse_find so it can be very slow. 
278  *
279  * It won't have a subelement, the ending's callbacks won't get called.
280  */
281
282 /*
283  * op_mode values determine how the terminating element and the current offset
284  * of the parser are handled 
285  */
286 tvbparse_wanted_t* tvbparse_until(const int id,
287                                                                   const void* private_data,
288                                                                   tvbparse_action_t before_cb,
289                                                                   tvbparse_action_t after_cb,
290                                                                   const tvbparse_wanted_t* ending,
291                                                                   until_mode_t until_mode);
292
293 /*
294  * one_of
295  *
296  * When looked for it will try to match to the given candidates and return a
297  * composed element whose subelement is the first match.
298  *
299  * The list of candidates is terminated with a NULL
300  *
301  */
302 tvbparse_wanted_t* tvbparse_set_oneof(const int id,
303                                                                           const void* private_data,
304                                                                           tvbparse_action_t before_cb,
305                                                                           tvbparse_action_t after_cb,
306                                                                           ...);
307
308 /* 
309  * hashed
310  */
311
312 tvbparse_wanted_t* tvbparse_hashed(const int id,
313                                    const void* data, 
314                                    tvbparse_action_t before_cb,
315                                    tvbparse_action_t after_cb,
316                                    tvbparse_wanted_t* key,
317                                    tvbparse_wanted_t* other,
318                                    ...);
319
320 void tvbparse_hashed_add(tvbparse_wanted_t* w, ...);
321
322 /*
323  * sequence
324  *
325  * When looked for it will try to match in order all the given candidates. If
326  * every candidate is found in the given order it will return a composed
327  * element whose subelements are the matcheed elemets.
328  *
329  * The list of candidates is terminated with a NULL.
330  *
331  */
332 tvbparse_wanted_t* tvbparse_set_seq(const int id,
333                                                                         const void* private_data,
334                                                                         tvbparse_action_t before_cb,
335                                                                         tvbparse_action_t after_cb,
336                                                                         ...);
337 /*
338  * some
339  *
340  * When looked for it will try to match the given candidate at least min times
341  * and at most max times. If the given candidate is matched at least min times
342  * a composed element is returned.
343  *
344  */
345 tvbparse_wanted_t* tvbparse_some(const int id,
346                                                                  const guint min,
347                                                                  const guint max,
348                                                                  const void* private_data,
349                                                                  tvbparse_action_t before_cb,
350                                                                  tvbparse_action_t after_cb,
351                                                                  const tvbparse_wanted_t* wanted);
352
353 #define tvbparse_one_or_more(id, private_data, before_cb, after_cb, wanted)\
354         tvbparse_some(id, 1, G_MAXINT, private_data, before_cb, after_cb, wanted)
355
356
357 /* 
358  * handle
359  *
360  * this is a pointer to a pointer to a wanted element (that might have not
361  * been initialized yet) so that recursive structures
362  */
363 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle);
364
365 #if 0
366
367 enum ft_cmp_op {
368     TVBPARSE_CMP_GT,
369     TVBPARSE_CMP_GE,
370     TVBPARSE_CMP_EQ,
371     TVBPARSE_CMP_NE,
372     TVBPARSE_CMP_LE,
373     TVBPARSE_CMP_LT
374 };
375
376 /* not yet tested */
377 tvbparse_wanted_t* tvbparse_ft(int id,
378                                const void* data,
379                                tvbparse_action_t before_cb,
380                                tvbparse_action_t after_cb,
381                                enum ftenum ftenum);
382
383 /* not yet tested */
384 tvbparse_wanted_t* tvbparse_end_of_buffer(int id,
385                                           const void* data,
386                                           tvbparse_action_t before_cb,
387                                           tvbparse_action_t after_cb);
388 /* not yet tested */
389 tvbparse_wanted_t* tvbparse_ft_numcmp(int id,
390                                       const void* data,
391                                       tvbparse_action_t before_cb,
392                                       tvbparse_action_t after_cb,
393                                       enum ftenum ftenum,
394                                       int little_endian,
395                                       enum ft_cmp_op ft_cmp_op,
396                                       ... );
397
398 #endif
399
400 /*  quoted
401  *  this is a composed candidate, that will try to match a quoted string
402  *  (included the quotes) including into it every escaped quote.
403  *
404  *  C strings are matched with tvbparse_quoted(-1,NULL,NULL,NULL,"\"","\\")
405  */
406 tvbparse_wanted_t* tvbparse_quoted(const int id,
407                                                                    const void* data,
408                                                                    tvbparse_action_t before_cb,
409                                                                    tvbparse_action_t after_cb,
410                                                                    const char quote,
411                                                                    const char escape);
412
413 /*
414  * a helper callback for quoted strings that will shrink the token to contain
415  * only the string andnot the quotes
416  */
417 void tvbparse_shrink_token_cb(void* tvbparse_data,
418                                                           const void* wanted_data,
419                                                           tvbparse_elem_t* tok);
420
421
422
423
424 /* initialize the parser (at every packet)
425 * tvb: what are we parsing? 
426 * offset: from where
427 * len: for how many bytes
428 * private_data: will be passed to the action callbacks 
429 * ignore: a wanted token type to be ignored (the associated cb WILL be called when it matches)
430 */
431 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
432                                                   const int offset,
433                                                   int len,
434                                                   void* private_data,
435                                                   const tvbparse_wanted_t* ignore);
436
437 /* reset the parser */
438 gboolean tvbparse_reset(tvbparse_t* tt, int offset, int len);
439
440 guint tvbparse_curr_offset(tvbparse_t* tt);
441 guint tvbparse_len_left(tvbparse_t* tt);
442
443
444
445 /*
446  * This will look for the wanted token at the current offset or after any given
447  * number of ignored tokens returning FALSE if there's no match or TRUE if there
448  * is a match.
449  * The parser will be left in its original state and no callbacks will be called. 
450  */
451 gboolean tvbparse_peek(tvbparse_t* tt,
452                         const tvbparse_wanted_t* wanted);
453
454 /*
455  * This will look for the wanted token at the current offset or after any given
456  * number of ignored tokens returning NULL if there's no match.
457  * if there is a match it will set the offset of the current parser after
458  * the end of the token 
459  */
460 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
461                                                           const tvbparse_wanted_t* wanted);
462
463 /*
464  * Like tvbparse_get but this will look for a wanted token even beyond the
465  * current offset.
466  * This function is slow.
467  */
468
469 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt,
470                                                            const tvbparse_wanted_t* wanted);
471
472
473 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr);
474
475 #endif