/src/wireshark/epan/tvbparse.c
Line | Count | Source |
1 | | /* tvbparse.c |
2 | | * |
3 | | * Copyright 2005, Luis E. Garcia Ontanon <luis@ontanon.org> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
14 | | #include <stdlib.h> |
15 | | #include <string.h> |
16 | | #include <glib.h> |
17 | | |
18 | | #include <epan/wmem_scopes.h> |
19 | | #include <epan/proto.h> |
20 | | #include <epan/packet_info.h> |
21 | | #include <epan/tvbparse.h> |
22 | | #include <wsutil/ws_assert.h> |
23 | | |
24 | | |
25 | | #define TVBPARSE_DEBUG_ALL 0xffffffff |
26 | | |
27 | | #if 0 |
28 | | #define TVBPARSE_DEBUG_ 0x80000000 |
29 | | #define TVBPARSE_DEBUG_ 0x40000000 |
30 | | #define TVBPARSE_DEBUG_ 0x20000000 |
31 | | #define TVBPARSE_DEBUG_ 0x10000000 |
32 | | #endif |
33 | | |
34 | | #define TVBPARSE_DEBUG_CHAR 0x08000000 |
35 | | #define TVBPARSE_DEBUG_CHARS 0x04000000 |
36 | | #define TVBPARSE_DEBUG_NOT_CHAR 0x02000000 |
37 | | #define TVBPARSE_DEBUG_NOT_CHARS 0x01000000 |
38 | | #define TVBPARSE_DEBUG_STRING 0x00800000 |
39 | | #define TVBPARSE_DEBUG_CASESTRING 0x00400000 |
40 | | #define TVBPARSE_DEBUG_ONEOF 0x00200000 |
41 | | #define TVBPARSE_DEBUG_HASH 0x00100000 |
42 | | #define TVBPARSE_DEBUG_SEQ 0x00080000 |
43 | | #define TVBPARSE_DEBUG_SOME 0x00040000 |
44 | | #define TVBPARSE_DEBUG_UNTIL 0x00020000 |
45 | | #if 0 |
46 | | #define TVBPARSE_DEBUG_ 0x00010000 |
47 | | #define TVBPARSE_DEBUG_ 0x00008000 |
48 | | #define TVBPARSE_DEBUG_ 0x00004000 |
49 | | #define TVBPARSE_DEBUG_ 0x00002000 |
50 | | #define TVBPARSE_DEBUG_ 0x00001000 |
51 | | #endif |
52 | | #define TVBPARSE_DEBUG_TT 0x00000800 |
53 | | #define TVBPARSE_DEBUG_CB 0x00000400 |
54 | | #define TVBPARSE_DEBUG_GET 0x00000200 |
55 | | #define TVBPARSE_DEBUG_FIND 0x00000100 |
56 | | #define TVBPARSE_DEBUG_NEWTOK 0x00000080 |
57 | | #define TVBPARSE_DEBUG_IGNORE 0x00000040 |
58 | | #define TVBPARSE_DEBUG_PEEK 0x00000020 |
59 | | #if 0 |
60 | | #define TVBPARSE_DEBUG_ 0x00000010 |
61 | | #define TVBPARSE_DEBUG_ 0x00000008 |
62 | | #define TVBPARSE_DEBUG_ 0x00000004 |
63 | | #define TVBPARSE_DEBUG_ 0x00000002 |
64 | | #define TVBPARSE_DEBUG_ 0x00000001 |
65 | | #endif |
66 | | |
67 | | /* |
68 | | #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME) |
69 | | */ |
70 | | |
71 | 442k | #define TVBPARSE_MAX_RECURSION_DEPTH 100 // Arbitrary. Matches DAAP and PNIO. |
72 | | |
73 | | static tvbparse_elem_t* new_tok(tvbparse_t* tt, |
74 | | int id, |
75 | | int offset, |
76 | | int len, |
77 | 374k | const tvbparse_wanted_t* wanted) { |
78 | 374k | tvbparse_elem_t* tok; |
79 | | |
80 | | #ifdef TVBPARSE_DEBUG |
81 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) ws_warning("new_tok: id=%i offset=%u len=%u",id,offset,len); |
82 | | #endif |
83 | | |
84 | 374k | tok = wmem_new(tt->scope, tvbparse_elem_t); |
85 | | |
86 | 374k | tok->parser = tt; |
87 | 374k | tok->tvb = tt->tvb; |
88 | 374k | tok->id = id; |
89 | 374k | tok->offset = offset; |
90 | 374k | tok->len = len; |
91 | 374k | tok->data = NULL; |
92 | 374k | tok->sub = NULL; |
93 | 374k | tok->next = NULL; |
94 | 374k | tok->wanted = wanted; |
95 | 374k | tok->last = tok; |
96 | | |
97 | 374k | return tok; |
98 | 374k | } |
99 | | |
100 | 209k | static int ignore_fcn(tvbparse_t* tt, int offset) { |
101 | 209k | int len = 0; |
102 | 209k | int consumed; |
103 | 209k | tvbparse_elem_t* ignored = NULL; |
104 | | |
105 | 209k | if (!tt->ignore) return 0; |
106 | | |
107 | | #ifdef TVBPARSE_DEBUG |
108 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_warning("ignore: enter"); |
109 | | #endif |
110 | | |
111 | 239k | while ((consumed = tt->ignore->condition(tt,offset,tt->ignore,&ignored)) > 0) { |
112 | 29.7k | len += consumed; |
113 | 29.7k | offset += consumed; |
114 | | #ifdef TVBPARSE_DEBUG |
115 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_warning("ignore: consumed=%i",consumed); |
116 | | #endif |
117 | | |
118 | 29.7k | } |
119 | | |
120 | | #ifdef TVBPARSE_DEBUG |
121 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) ws_warning("ignore: len=%i",len); |
122 | | #endif |
123 | | |
124 | 209k | return len; |
125 | 209k | } |
126 | | |
127 | | |
128 | 348k | static int cond_char (tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
129 | 348k | char c,t; |
130 | 348k | unsigned i; |
131 | | |
132 | | #ifdef TVBPARSE_DEBUG |
133 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) ws_warning("cond_char: control='%s'",wanted->control.str); |
134 | | #endif |
135 | | |
136 | 348k | if ( offset + 1 > tt->end_offset ) |
137 | 0 | return -1; |
138 | | |
139 | 348k | t = (char) tvb_get_uint8(tt->tvb,offset); |
140 | | |
141 | 600k | for(i = 0; (c = wanted->control.str[i]) && offset <= tt->end_offset; i++) { |
142 | 352k | if ( c == t ) { |
143 | 101k | *tok = new_tok(tt,wanted->id,offset,1,wanted); |
144 | | #ifdef TVBPARSE_DEBUG |
145 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) ws_warning("cond_char: GOT: '%c'",c); |
146 | | #endif |
147 | 101k | return 1; |
148 | 101k | } |
149 | 352k | } |
150 | | |
151 | 247k | return -1; |
152 | 348k | } |
153 | | |
154 | | tvbparse_wanted_t* tvbparse_char(const int id, |
155 | | const char* chr, |
156 | | const void* data, |
157 | | tvbparse_action_t before_cb, |
158 | 504 | tvbparse_action_t after_cb) { |
159 | 504 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
160 | | |
161 | 504 | w->condition = cond_char; |
162 | 504 | w->id = id; |
163 | 504 | w->control.str = chr; |
164 | 504 | w->len = 1; |
165 | 504 | w->data = data; |
166 | 504 | w->before = before_cb; |
167 | 504 | w->after = after_cb; |
168 | | |
169 | 504 | return w; |
170 | 504 | } |
171 | | |
172 | 327k | static int cond_chars_common(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
173 | 327k | unsigned length = 0; |
174 | 327k | int start = offset; |
175 | 327k | int left = tt->end_offset - offset; |
176 | | |
177 | | #ifdef TVBPARSE_DEBUG |
178 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) ws_warning("cond_chars_common: control='%s'",wanted->control.str); |
179 | | #endif |
180 | | |
181 | 327k | if ( offset + (int)wanted->min > tt->end_offset ) |
182 | 8.65k | return -1; |
183 | | |
184 | 319k | left = left < (int) wanted->max ? left : (int) wanted->max; |
185 | | |
186 | 654k | while( left > 0 ) { |
187 | 647k | uint8_t t = tvb_get_uint8(tt->tvb,offset++); |
188 | | |
189 | 647k | if (!wanted->control.str[t]) |
190 | 312k | break; |
191 | | |
192 | 335k | length++; |
193 | 335k | left--; |
194 | 335k | }; |
195 | | |
196 | 319k | if (length < wanted->min) { |
197 | 249k | return -1; |
198 | 249k | } else { |
199 | 69.3k | *tok = new_tok(tt,wanted->id,start,length,wanted); |
200 | | #ifdef TVBPARSE_DEBUG |
201 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) ws_warning("cond_chars_common: GOT len=%i",length); |
202 | | #endif |
203 | 69.3k | return length; |
204 | 69.3k | } |
205 | 319k | } |
206 | | |
207 | | tvbparse_wanted_t* tvbparse_chars(const int id, |
208 | | const unsigned min_len, |
209 | | const unsigned max_len, |
210 | | const char* chr, |
211 | | const void* data, |
212 | | tvbparse_action_t before_cb, |
213 | | tvbparse_action_t after_cb) |
214 | 322 | { |
215 | 322 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
216 | 322 | char *accept_str; |
217 | 322 | size_t i; |
218 | | |
219 | 322 | accept_str = (char *)wmem_alloc(wmem_epan_scope(), 256); |
220 | 322 | memset(accept_str, 0x00, 256); |
221 | 6.77k | for (i = 0; chr[i]; i++) |
222 | 6.45k | accept_str[(unsigned)chr[i]] = (char)0xFF; |
223 | | |
224 | 322 | w->condition = cond_chars_common; |
225 | 322 | w->id = id; |
226 | 322 | w->control.str = accept_str; |
227 | 322 | w->min = min_len ? min_len : 1; |
228 | 322 | w->max = max_len ? max_len : INT_MAX/2; |
229 | 322 | w->data = data; |
230 | 322 | w->before = before_cb; |
231 | 322 | w->after = after_cb; |
232 | | |
233 | 322 | return w; |
234 | 322 | } |
235 | | |
236 | | |
237 | 0 | static int cond_not_char(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
238 | 0 | char c, t; |
239 | 0 | unsigned i; |
240 | 0 | bool not_matched = false; |
241 | |
|
242 | | #ifdef TVBPARSE_DEBUG |
243 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) ws_warning("cond_not_char: control='%s'",wanted->control.str); |
244 | | #endif |
245 | |
|
246 | 0 | if ( offset >= tt->end_offset ) { |
247 | 0 | return -1; |
248 | 0 | } |
249 | | |
250 | 0 | t = (char) tvb_get_uint8(tt->tvb,offset); |
251 | |
|
252 | 0 | for(i = 0; (c = wanted->control.str[i]); i++) { |
253 | 0 | if ( c == t ) { |
254 | 0 | not_matched = true; |
255 | 0 | } |
256 | 0 | } |
257 | |
|
258 | 0 | if (not_matched) { |
259 | 0 | return -1; |
260 | 0 | } else { |
261 | 0 | *tok = new_tok(tt,wanted->id,offset,1,wanted); |
262 | | #ifdef TVBPARSE_DEBUG |
263 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) ws_warning("cond_not_char: GOT='%c'",t); |
264 | | #endif |
265 | 0 | return 1; |
266 | 0 | } |
267 | 0 | } |
268 | | |
269 | | tvbparse_wanted_t* tvbparse_not_char(const int id, |
270 | | const char* chr, |
271 | | const void* data, |
272 | | tvbparse_action_t before_cb, |
273 | 0 | tvbparse_action_t after_cb) { |
274 | 0 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
275 | |
|
276 | 0 | w->condition = cond_not_char; |
277 | 0 | w->id = id; |
278 | 0 | w->control.str = chr; |
279 | 0 | w->data = data; |
280 | 0 | w->before = before_cb; |
281 | 0 | w->after = after_cb; |
282 | |
|
283 | 0 | return w; |
284 | 0 | } |
285 | | |
286 | | tvbparse_wanted_t* tvbparse_not_chars(const int id, |
287 | | const unsigned min_len, |
288 | | const unsigned max_len, |
289 | | const char* chr, |
290 | | const void* data, |
291 | | tvbparse_action_t before_cb, |
292 | | tvbparse_action_t after_cb) |
293 | 112 | { |
294 | 112 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
295 | 112 | char *accept_str; |
296 | 112 | size_t i; |
297 | | |
298 | | /* cond_chars_common() use accept string, so mark all elements with, and later unset from reject */ |
299 | 112 | accept_str = (char *)wmem_alloc(wmem_epan_scope(), 256); |
300 | 112 | memset(accept_str, 0xFF, 256); |
301 | 294 | for (i = 0; chr[i]; i++) |
302 | 182 | accept_str[(unsigned) chr[i]] = '\0'; |
303 | | |
304 | 112 | w->condition = cond_chars_common; |
305 | 112 | w->id = id; |
306 | 112 | w->control.str = accept_str; |
307 | 112 | w->len = 0; |
308 | 112 | w->min = min_len ? min_len : 1; |
309 | 112 | w->max = max_len ? max_len : INT_MAX/2; |
310 | 112 | w->data = data; |
311 | 112 | w->before = before_cb; |
312 | 112 | w->after = after_cb; |
313 | | |
314 | 112 | return w; |
315 | 112 | } |
316 | | |
317 | | |
318 | 199k | static int cond_string(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
319 | 199k | int len = wanted->len; |
320 | | #ifdef TVBPARSE_DEBUG |
321 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) ws_warning("cond_string: control='%s'",wanted->control.str); |
322 | | #endif |
323 | | |
324 | 199k | if ( offset + wanted->len > tt->end_offset ) |
325 | 426 | return -1; |
326 | | |
327 | 199k | if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) { |
328 | 5.31k | *tok = new_tok(tt,wanted->id,offset,len,wanted); |
329 | | #ifdef TVBPARSE_DEBUG |
330 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) ws_warning("cond_string: GOT len=%i",len); |
331 | | #endif |
332 | 5.31k | return len; |
333 | 193k | } else { |
334 | 193k | return -1; |
335 | 193k | } |
336 | 199k | } |
337 | | |
338 | | tvbparse_wanted_t* tvbparse_string(const int id, |
339 | | const char* str, |
340 | | const void* data, |
341 | | tvbparse_action_t before_cb, |
342 | 364 | tvbparse_action_t after_cb) { |
343 | 364 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
344 | | |
345 | 364 | w->condition = cond_string; |
346 | 364 | w->id = id; |
347 | 364 | w->control.str = str; |
348 | 364 | w->len = (int) strlen(str); |
349 | 364 | w->data = data; |
350 | 364 | w->before = before_cb; |
351 | 364 | w->after = after_cb; |
352 | | |
353 | 364 | return w; |
354 | 364 | } |
355 | | |
356 | 1.47k | static int cond_casestring(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
357 | 1.47k | int len = wanted->len; |
358 | | #ifdef TVBPARSE_DEBUG |
359 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) ws_warning("cond_casestring: control='%s'",wanted->control.str); |
360 | | #endif |
361 | | |
362 | 1.47k | if ( offset + len > tt->end_offset ) |
363 | 0 | return -1; |
364 | | |
365 | 1.47k | if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) { |
366 | 369 | *tok = new_tok(tt,wanted->id,offset,len,wanted); |
367 | | #ifdef TVBPARSE_DEBUG |
368 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) ws_warning("cond_casestring: GOT len=%i",len); |
369 | | #endif |
370 | 369 | return len; |
371 | 1.10k | } else { |
372 | 1.10k | *tok = NULL; |
373 | 1.10k | return -1; |
374 | 1.10k | } |
375 | 1.47k | } |
376 | | |
377 | | tvbparse_wanted_t* tvbparse_casestring(const int id, |
378 | | const char* str, |
379 | | const void* data, |
380 | | tvbparse_action_t before_cb, |
381 | 42 | tvbparse_action_t after_cb) { |
382 | 42 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
383 | | |
384 | 42 | w->condition = cond_casestring; |
385 | 42 | w->id = id; |
386 | 42 | w->control.str = str; |
387 | 42 | w->len = (int) strlen(str); |
388 | 42 | w->data = data; |
389 | 42 | w->before = before_cb; |
390 | 42 | w->after = after_cb; |
391 | | |
392 | 42 | return w; |
393 | 42 | } |
394 | | |
395 | 92.5k | static int cond_one_of(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
396 | 92.5k | unsigned i; |
397 | | #ifdef TVBPARSE_DEBUG |
398 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) ws_warning("cond_one_of: START"); |
399 | | #endif |
400 | | |
401 | 92.5k | if ( offset > tt->end_offset ) |
402 | 0 | return -1; |
403 | | |
404 | 92.5k | if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH) |
405 | 70 | return -1; |
406 | | |
407 | 413k | for(i=0; i < wanted->control.elems->len; i++) { |
408 | 387k | tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i); |
409 | 387k | tvbparse_elem_t* new_elem = NULL; |
410 | 387k | int curr_len; |
411 | | |
412 | 387k | if ( offset + w->len > tt->end_offset ) |
413 | 2.94k | continue; |
414 | | |
415 | 384k | curr_len = w->condition(tt, offset, w, &new_elem); |
416 | | |
417 | 384k | if (curr_len >= 0) { |
418 | 66.9k | *tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted); |
419 | 66.9k | (*tok)->sub = new_elem; |
420 | | #ifdef TVBPARSE_DEBUG |
421 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) ws_warning("cond_one_of: GOT len=%i",curr_len); |
422 | | #endif |
423 | 66.9k | tt->recursion_depth--; |
424 | 66.9k | return curr_len; |
425 | 66.9k | } |
426 | 384k | } |
427 | | |
428 | 25.5k | tt->recursion_depth--; |
429 | 25.5k | return -1; |
430 | 92.4k | } |
431 | | |
432 | | static bool |
433 | | tvbparse_wanted_cleanup_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data) |
434 | 0 | { |
435 | 0 | tvbparse_wanted_t* w = (tvbparse_wanted_t *)user_data; |
436 | 0 | g_ptr_array_free(w->control.elems, true); |
437 | 0 | return false; |
438 | 0 | } |
439 | | |
440 | | tvbparse_wanted_t* tvbparse_set_oneof(const int id, |
441 | | const void* data, |
442 | | tvbparse_action_t before_cb, |
443 | | tvbparse_action_t after_cb, |
444 | 364 | ...) { |
445 | 364 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
446 | 364 | tvbparse_t* el; |
447 | 364 | va_list ap; |
448 | | |
449 | 364 | w->condition = cond_one_of; |
450 | 364 | w->id = id; |
451 | 364 | w->data = data; |
452 | 364 | w->before = before_cb; |
453 | 364 | w->after = after_cb; |
454 | 364 | w->control.elems = g_ptr_array_new(); |
455 | 364 | wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb, w); |
456 | | |
457 | 364 | va_start(ap,after_cb); |
458 | | |
459 | 1.49k | while(( el = va_arg(ap,tvbparse_t*) )) { |
460 | 1.13k | g_ptr_array_add(w->control.elems,el); |
461 | 1.13k | }; |
462 | | |
463 | 364 | va_end(ap); |
464 | | |
465 | 364 | return w; |
466 | 364 | } |
467 | | |
468 | 0 | static int cond_hash(tvbparse_t* tt, const int offset, const tvbparse_wanted_t* wanted, tvbparse_elem_t** tok) { |
469 | 0 | int key_len; |
470 | 0 | uint8_t* key = NULL; |
471 | 0 | tvbparse_elem_t* key_elem = NULL; |
472 | 0 | tvbparse_wanted_t* value_wanted = NULL; |
473 | 0 | int value_len; |
474 | 0 | tvbparse_elem_t* value_elem = NULL; |
475 | 0 | int tot_len; |
476 | 0 | tvbparse_elem_t* ret_tok; |
477 | |
|
478 | | #ifdef TVBPARSE_DEBUG |
479 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_warning("cond_hash: START"); |
480 | | #endif |
481 | |
|
482 | 0 | if ( offset > tt->end_offset ) |
483 | 0 | return -1; |
484 | | |
485 | 0 | if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH) |
486 | 0 | return -1; |
487 | | |
488 | 0 | key_len = wanted->control.hash.key->condition(tt, offset, wanted->control.hash.key, &key_elem); |
489 | |
|
490 | 0 | if (key_len < 0) { |
491 | 0 | tt->recursion_depth--; |
492 | 0 | return -1; |
493 | 0 | } |
494 | | |
495 | 0 | key = tvb_get_string_enc(tt->scope,key_elem->parser->tvb,key_elem->offset,key_elem->len, ENC_ASCII); |
496 | | #ifdef TVBPARSE_DEBUG |
497 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_warning("cond_hash: got key='%s'",key); |
498 | | #endif |
499 | |
|
500 | 0 | if ((value_wanted = (tvbparse_wanted_t *)wmem_map_lookup(wanted->control.hash.table,key))) { |
501 | 0 | value_len = value_wanted->condition(tt, offset + key_len, value_wanted, &value_elem); |
502 | 0 | } else if (wanted->control.hash.other) { |
503 | 0 | value_len = wanted->control.hash.other->condition(tt, offset+key_len, wanted->control.hash.other, &value_elem); |
504 | 0 | if (value_len < 0) { |
505 | 0 | tt->recursion_depth--; |
506 | 0 | return -1; |
507 | 0 | } |
508 | 0 | } else { |
509 | 0 | tt->recursion_depth--; |
510 | 0 | return -1; |
511 | 0 | } |
512 | | |
513 | 0 | tt->recursion_depth--; |
514 | |
|
515 | 0 | tot_len = key_len + value_len; |
516 | |
|
517 | 0 | ret_tok = new_tok(tt, value_elem->id, offset, tot_len, wanted); |
518 | 0 | ret_tok->sub = key_elem; |
519 | 0 | ret_tok->sub->last->next = value_elem; |
520 | |
|
521 | 0 | *tok = ret_tok; |
522 | | #ifdef TVBPARSE_DEBUG |
523 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) ws_warning("cond_hash: GOT len=%i",tot_len); |
524 | | #endif |
525 | |
|
526 | 0 | return tot_len; |
527 | 0 | } |
528 | | |
529 | | tvbparse_wanted_t* tvbparse_hashed(const int id, |
530 | | const void* data, |
531 | | tvbparse_action_t before_cb, |
532 | | tvbparse_action_t after_cb, |
533 | | tvbparse_wanted_t* key, |
534 | | tvbparse_wanted_t* other, |
535 | 0 | ...) { |
536 | 0 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
537 | 0 | char* name; |
538 | 0 | tvbparse_wanted_t* el; |
539 | 0 | va_list ap; |
540 | |
|
541 | 0 | w->condition = cond_hash; |
542 | 0 | w->id = id; |
543 | 0 | w->data = data; |
544 | 0 | w->before = before_cb; |
545 | 0 | w->after = after_cb; |
546 | 0 | w->control.hash.table = wmem_map_new(wmem_epan_scope(), g_str_hash,g_str_equal); |
547 | 0 | w->control.hash.key = key; |
548 | 0 | w->control.hash.other = other; |
549 | |
|
550 | 0 | va_start(ap,other); |
551 | |
|
552 | 0 | while(( name = va_arg(ap,char*) )) { |
553 | 0 | el = va_arg(ap,tvbparse_wanted_t*); |
554 | 0 | wmem_map_insert(w->control.hash.table,name,el); |
555 | 0 | } |
556 | |
|
557 | 0 | va_end(ap); |
558 | |
|
559 | 0 | return w; |
560 | 0 | } |
561 | | |
562 | 0 | void tvbparse_hashed_add(tvbparse_wanted_t* w, ...) { |
563 | 0 | tvbparse_wanted_t* el; |
564 | 0 | va_list ap; |
565 | 0 | char* name; |
566 | |
|
567 | 0 | va_start(ap,w); |
568 | |
|
569 | 0 | while (( name = va_arg(ap,char*) )) { |
570 | 0 | el = va_arg(ap,tvbparse_wanted_t*); |
571 | 0 | wmem_map_insert(w->control.hash.table,name,el); |
572 | 0 | } |
573 | |
|
574 | 0 | va_end(ap); |
575 | 0 | } |
576 | | |
577 | 312k | static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
578 | 312k | unsigned i; |
579 | 312k | int len = 0; |
580 | 312k | int start = offset; |
581 | 312k | tvbparse_elem_t* ret_tok = NULL; |
582 | | |
583 | | #ifdef TVBPARSE_DEBUG |
584 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) ws_warning("cond_seq: START"); |
585 | | #endif |
586 | | |
587 | 312k | if ( offset > tt->end_offset ) |
588 | 0 | return -1; |
589 | | |
590 | 312k | if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH) |
591 | 228 | return -1; |
592 | | |
593 | 488k | for(i=0; i < wanted->control.elems->len; i++) { |
594 | 445k | tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i); |
595 | 445k | tvbparse_elem_t* new_elem = NULL; |
596 | | |
597 | 445k | if ( offset + w->len > tt->end_offset ) { |
598 | 17.8k | tt->recursion_depth--; |
599 | 17.8k | return -1; |
600 | 17.8k | } |
601 | | |
602 | 428k | len = w->condition(tt, offset, w, &new_elem); |
603 | | |
604 | 428k | if (len >= 0) { |
605 | 175k | if (ret_tok) { |
606 | 73.9k | if (new_elem->len) |
607 | 56.9k | ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len; |
608 | 73.9k | ret_tok->sub->last->next = new_elem; |
609 | 73.9k | ret_tok->sub->last = new_elem; |
610 | 101k | } else { |
611 | 101k | ret_tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted); |
612 | 101k | ret_tok->sub = new_elem; |
613 | 101k | new_elem->last = new_elem; |
614 | 101k | } |
615 | 252k | } else { |
616 | 252k | tt->recursion_depth--; |
617 | 252k | return -1; |
618 | 252k | } |
619 | | |
620 | 175k | offset += len; |
621 | 175k | offset += ignore_fcn(tt,offset); |
622 | 175k | } |
623 | | |
624 | 42.3k | tt->recursion_depth--; |
625 | | |
626 | 42.3k | *tok = ret_tok; |
627 | | |
628 | | #ifdef TVBPARSE_DEBUG |
629 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) ws_warning("cond_seq: GOT len=%i",offset - start); |
630 | | #endif |
631 | | |
632 | 42.3k | return offset - start; |
633 | 312k | } |
634 | | |
635 | | |
636 | | tvbparse_wanted_t* tvbparse_set_seq(const int id, |
637 | | const void* data, |
638 | | tvbparse_action_t before_cb, |
639 | | tvbparse_action_t after_cb, |
640 | 630 | ...) { |
641 | 630 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
642 | 630 | tvbparse_wanted_t* el = NULL; |
643 | 630 | va_list ap; |
644 | | |
645 | 630 | w->condition = cond_seq; |
646 | 630 | w->id = id; |
647 | 630 | w->data = data; |
648 | 630 | w->before = before_cb; |
649 | 630 | w->after = after_cb; |
650 | 630 | w->control.elems = g_ptr_array_new(); |
651 | 630 | wmem_register_callback(wmem_epan_scope(), tvbparse_wanted_cleanup_cb, w); |
652 | | |
653 | 630 | va_start(ap,after_cb); |
654 | | |
655 | 2.22k | while(( el = va_arg(ap,tvbparse_wanted_t*) )) { |
656 | 1.59k | g_ptr_array_add(w->control.elems,el); |
657 | 1.59k | }; |
658 | | |
659 | 630 | va_end(ap); |
660 | 630 | return w; |
661 | 630 | } |
662 | | |
663 | 35.5k | static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
664 | 35.5k | unsigned got_so_far = 0; |
665 | 35.5k | int start = offset; |
666 | 35.5k | tvbparse_elem_t* ret_tok = NULL; |
667 | | #ifdef TVBPARSE_DEBUG |
668 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_warning("cond_some: START"); |
669 | | #endif |
670 | | |
671 | 35.5k | if ( offset > tt->end_offset ) |
672 | 0 | return -1; |
673 | | |
674 | 35.5k | if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH) |
675 | 87 | return -1; |
676 | | |
677 | 35.4k | if ( wanted->min == 0 ) { |
678 | 28.6k | ret_tok = new_tok(tt,wanted->id,offset,0,wanted); |
679 | 28.6k | } |
680 | | |
681 | 48.6k | while (got_so_far < wanted->max) { |
682 | 45.6k | tvbparse_elem_t* new_elem = NULL; |
683 | 45.6k | int consumed; |
684 | | |
685 | 45.6k | if ( offset > tt->end_offset ) { |
686 | 0 | tt->recursion_depth--; |
687 | 0 | return -1; |
688 | 0 | } |
689 | | |
690 | 45.6k | consumed = wanted->control.subelem->condition(tt, offset, wanted->control.subelem, &new_elem); |
691 | | |
692 | 45.6k | if(consumed >= 0) { |
693 | 13.2k | if (ret_tok) { |
694 | 12.4k | if (new_elem->len) |
695 | 12.4k | ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len; |
696 | | |
697 | 12.4k | if (ret_tok->sub) { |
698 | 8.09k | ret_tok->sub->last->next = new_elem; |
699 | 8.09k | ret_tok->sub->last = new_elem; |
700 | 8.09k | } else { |
701 | 4.39k | ret_tok->sub = new_elem; |
702 | 4.39k | } |
703 | 12.4k | } else { |
704 | 781 | ret_tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted); |
705 | 781 | ret_tok->sub = new_elem; |
706 | 781 | } |
707 | 32.3k | } else { |
708 | 32.3k | break; |
709 | 32.3k | } |
710 | | |
711 | 13.2k | offset += consumed; |
712 | 13.2k | got_so_far++; |
713 | 13.2k | } |
714 | | |
715 | 35.4k | tt->recursion_depth--; |
716 | | |
717 | | #ifdef TVBPARSE_DEBUG |
718 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_warning("cond_some: got num=%u",got_so_far); |
719 | | #endif |
720 | | |
721 | 35.4k | if(got_so_far < wanted->min) { |
722 | 5.99k | return -1; |
723 | 5.99k | } |
724 | | |
725 | 29.4k | *tok = ret_tok; |
726 | | #ifdef TVBPARSE_DEBUG |
727 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) ws_warning("cond_some: GOT len=%i",offset - start); |
728 | | #endif |
729 | 29.4k | return offset - start; |
730 | 35.4k | } |
731 | | |
732 | | tvbparse_wanted_t* tvbparse_some(const int id, |
733 | | const unsigned min, |
734 | | const unsigned max, |
735 | | const void* data, |
736 | | tvbparse_action_t before_cb, |
737 | | tvbparse_action_t after_cb, |
738 | 210 | const tvbparse_wanted_t* wanted) { |
739 | | |
740 | 210 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
741 | | |
742 | 210 | ws_assert(min <= max); |
743 | | |
744 | 210 | w->condition = cond_some; |
745 | 210 | w->id = id; |
746 | 210 | w->min = min; |
747 | 210 | w->max = max; |
748 | 210 | w->data = data; |
749 | 210 | w->before = before_cb; |
750 | 210 | w->after = after_cb; |
751 | 210 | w->control.subelem = wanted; |
752 | | |
753 | 210 | return w; |
754 | 210 | } |
755 | | |
756 | | |
757 | 1.88k | static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) { |
758 | 1.88k | tvbparse_elem_t* new_elem = NULL; |
759 | 1.88k | int len = 0; |
760 | 1.88k | int target_offset = offset; |
761 | | #ifdef TVBPARSE_DEBUG |
762 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_warning("cond_until: START"); |
763 | | #endif |
764 | | |
765 | 1.88k | if ( offset + wanted->control.until.subelem->len > tt->end_offset ) |
766 | 14 | return -1; |
767 | | |
768 | 1.87k | if (++tt->recursion_depth > TVBPARSE_MAX_RECURSION_DEPTH) |
769 | 0 | return -1; |
770 | | |
771 | 188k | do { |
772 | 188k | len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem, &new_elem); |
773 | 188k | } while(len < 0 && target_offset+1 < tt->end_offset); |
774 | | |
775 | 1.87k | tt->recursion_depth--; |
776 | | |
777 | 1.87k | if (len >= 0) { |
778 | | |
779 | 859 | new_elem->id = wanted->id; |
780 | 859 | new_elem->next = NULL; |
781 | 859 | new_elem->last = NULL; |
782 | 859 | new_elem->wanted = wanted; |
783 | 859 | new_elem->offset = offset; |
784 | | |
785 | 859 | (*tok) = new_elem; |
786 | | |
787 | 859 | switch (wanted->control.until.mode) { |
788 | 706 | case TP_UNTIL_INCLUDE: |
789 | 706 | new_elem->len = target_offset - offset - 1 + len; |
790 | | #ifdef TVBPARSE_DEBUG |
791 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_warning("cond_until: GOT len=%i",target_offset - offset -1 + len); |
792 | | #endif |
793 | 706 | return target_offset - offset -1 + len; |
794 | 153 | case TP_UNTIL_SPEND: |
795 | 153 | new_elem->len = target_offset - offset - 1; |
796 | | #ifdef TVBPARSE_DEBUG |
797 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_warning("cond_until: GOT len=%i",target_offset - offset -1 + len); |
798 | | #endif |
799 | 153 | return target_offset - offset - 1 + len; |
800 | 0 | case TP_UNTIL_LEAVE: |
801 | 0 | new_elem->len = target_offset - offset - 1; |
802 | | #ifdef TVBPARSE_DEBUG |
803 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) ws_warning("cond_until: GOT len=%i",target_offset - offset -1); |
804 | | #endif |
805 | 0 | return target_offset - offset -1; |
806 | 0 | default: |
807 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
808 | 0 | return -1; |
809 | 859 | } |
810 | | |
811 | 1.01k | } else { |
812 | 1.01k | return -1; |
813 | 1.01k | } |
814 | 1.87k | } |
815 | | |
816 | | tvbparse_wanted_t* tvbparse_until(const int id, |
817 | | const void* data, |
818 | | tvbparse_action_t before_cb, |
819 | | tvbparse_action_t after_cb, |
820 | | const tvbparse_wanted_t* el, |
821 | 70 | until_mode_t until_mode) { |
822 | 70 | tvbparse_wanted_t* w = wmem_new0(wmem_epan_scope(), tvbparse_wanted_t); |
823 | | |
824 | 70 | w->condition = cond_until; |
825 | 70 | w->control.until.mode = until_mode; |
826 | 70 | w->control.until.subelem = el; |
827 | 70 | w->id = id; |
828 | 70 | w->data = data; |
829 | 70 | w->before = before_cb; |
830 | 70 | w->after = after_cb; |
831 | | |
832 | 70 | return w; |
833 | 70 | } |
834 | | |
835 | | tvbparse_wanted_t* tvbparse_quoted(const int id, |
836 | | const void* data, |
837 | | tvbparse_action_t before_cb, |
838 | | tvbparse_action_t after_cb, |
839 | | const char quote, |
840 | 56 | const char esc) { |
841 | | |
842 | 56 | char* esc_quot = wmem_strdup_printf(wmem_epan_scope(), "%c%c",esc,quote); |
843 | 56 | char* quot = wmem_strdup_printf(wmem_epan_scope(), "%c",quote); |
844 | 56 | tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL); |
845 | | |
846 | 56 | return tvbparse_set_oneof(id, data, before_cb, after_cb, |
847 | 56 | tvbparse_set_seq(-1, NULL, NULL, NULL, |
848 | 56 | want_quot, |
849 | 56 | tvbparse_set_seq(-1,NULL,NULL,NULL, |
850 | 56 | tvbparse_set_oneof(-1, NULL, NULL, NULL, |
851 | 56 | tvbparse_string(-1,esc_quot,NULL,NULL,NULL), |
852 | 56 | tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL), |
853 | 56 | NULL), |
854 | 56 | NULL), |
855 | 56 | want_quot, |
856 | 56 | NULL), |
857 | 56 | tvbparse_set_seq(-1, NULL, NULL, NULL, |
858 | 56 | want_quot, |
859 | 56 | want_quot, |
860 | 56 | NULL), |
861 | 56 | NULL); |
862 | 56 | } |
863 | | |
864 | | void tvbparse_shrink_token_cb(void* tvbparse_data _U_, |
865 | | const void* wanted_data _U_, |
866 | 318 | tvbparse_elem_t* tok) { |
867 | 318 | tok->offset += 1; |
868 | 318 | tok->len -= 2; |
869 | 318 | } |
870 | | |
871 | | tvbparse_t* tvbparse_init(wmem_allocator_t *scope, |
872 | | tvbuff_t* tvb, |
873 | | const int offset, |
874 | | int len, |
875 | | void* data, |
876 | 4.37k | const tvbparse_wanted_t* ignore) { |
877 | 4.37k | tvbparse_t* tt = wmem_new(scope, tvbparse_t); |
878 | | |
879 | | #ifdef TVBPARSE_DEBUG |
880 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) ws_warning("tvbparse_init: offset=%i len=%i",offset,len); |
881 | | #endif |
882 | | |
883 | 4.37k | tt->scope = scope; |
884 | 4.37k | tt->tvb = tvb; |
885 | 4.37k | tt->offset = offset; |
886 | 4.37k | len = (len == -1) ? (int) tvb_captured_length(tvb) : len; |
887 | 4.37k | tt->end_offset = offset + len; |
888 | 4.37k | tt->data = data; |
889 | 4.37k | tt->ignore = ignore; |
890 | 4.37k | tt->recursion_depth = 0; |
891 | 4.37k | return tt; |
892 | 4.37k | } |
893 | | |
894 | | bool tvbparse_reset(tvbparse_t* tt, |
895 | | const unsigned offset, |
896 | 0 | unsigned len) { |
897 | |
|
898 | | #ifdef TVBPARSE_DEBUG |
899 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) ws_warning("tvbparse_init: offset=%i len=%i",offset,len); |
900 | | #endif |
901 | |
|
902 | 0 | if( tvb_captured_length_remaining(tt->tvb, offset) >= len) { |
903 | 0 | tt->offset = offset; |
904 | 0 | tt->end_offset = offset + len; |
905 | 0 | return true; |
906 | 0 | } else { |
907 | 0 | return false; |
908 | 0 | } |
909 | 0 | } |
910 | | |
911 | 2.66k | unsigned tvbparse_curr_offset(tvbparse_t* tt) { |
912 | 2.66k | return tt->offset; |
913 | 2.66k | } |
914 | | |
915 | 29.6k | static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) { |
916 | 29.6k | wmem_stack_t *stack = wmem_stack_new(tt->scope); |
917 | | |
918 | 228k | while (curr) { |
919 | 198k | if(curr->wanted->before) { |
920 | | #ifdef TVBPARSE_DEBUG |
921 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len); |
922 | | #endif |
923 | 11.3k | curr->wanted->before(tt->data, curr->wanted->data, curr); |
924 | 11.3k | } |
925 | | |
926 | 198k | if(curr->sub) { |
927 | 101k | wmem_stack_push(stack, curr); |
928 | 101k | curr = curr->sub; |
929 | 101k | continue; |
930 | 101k | } else { |
931 | | #ifdef TVBPARSE_DEBUG |
932 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len); |
933 | | #endif |
934 | 97.1k | if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr); |
935 | 97.1k | } |
936 | | |
937 | 97.1k | curr = curr->next; |
938 | | |
939 | 198k | while( !curr && wmem_stack_count(stack) > 0 ) { |
940 | 101k | curr = (tvbparse_elem_t *)wmem_stack_pop(stack); |
941 | | #ifdef TVBPARSE_DEBUG |
942 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) ws_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len); |
943 | | #endif |
944 | 101k | if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr); |
945 | 101k | curr = curr->next; |
946 | 101k | } |
947 | 97.1k | } |
948 | | |
949 | 29.6k | } |
950 | | |
951 | | bool tvbparse_peek(tvbparse_t* tt, |
952 | 0 | const tvbparse_wanted_t* wanted) { |
953 | 0 | tvbparse_elem_t* tok = NULL; |
954 | 0 | int consumed; |
955 | 0 | int offset = tt->offset; |
956 | |
|
957 | | #ifdef TVBPARSE_DEBUG |
958 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_warning("tvbparse_peek: ENTER offset=%i",offset); |
959 | | #endif |
960 | |
|
961 | 0 | offset += ignore_fcn(tt,offset); |
962 | |
|
963 | | #ifdef TVBPARSE_DEBUG |
964 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_warning("tvbparse_peek: after ignore offset=%i",offset); |
965 | | #endif |
966 | |
|
967 | 0 | consumed = wanted->condition(tt,offset,wanted,&tok); |
968 | |
|
969 | 0 | if (consumed >= 0) { |
970 | | #ifdef TVBPARSE_DEBUG |
971 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_warning("tvbparse_peek: GOT len=%i",consumed); |
972 | | #endif |
973 | 0 | return true; |
974 | 0 | } else { |
975 | | #ifdef TVBPARSE_DEBUG |
976 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) ws_warning("tvbparse_peek: NOT GOT"); |
977 | | #endif |
978 | 0 | return false; |
979 | 0 | } |
980 | |
|
981 | 0 | } |
982 | | |
983 | | tvbparse_elem_t* tvbparse_get(tvbparse_t* tt, |
984 | 34.0k | const tvbparse_wanted_t* wanted) { |
985 | 34.0k | tvbparse_elem_t* tok = NULL; |
986 | 34.0k | int consumed; |
987 | 34.0k | int offset = tt->offset; |
988 | | |
989 | | #ifdef TVBPARSE_DEBUG |
990 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_warning("tvbparse_get: ENTER offset=%i",offset); |
991 | | #endif |
992 | | |
993 | 34.0k | offset += ignore_fcn(tt,offset); |
994 | | |
995 | | #ifdef TVBPARSE_DEBUG |
996 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_warning("tvbparse_get: after ignore offset=%i",offset); |
997 | | #endif |
998 | | |
999 | 34.0k | consumed = wanted->condition(tt,offset,wanted,&tok); |
1000 | | |
1001 | 34.0k | if (consumed >= 0) { |
1002 | | #ifdef TVBPARSE_DEBUG |
1003 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_warning("tvbparse_get: GOT len=%i",consumed); |
1004 | | #endif |
1005 | 29.6k | execute_callbacks(tt,tok); |
1006 | 29.6k | tt->offset = offset + consumed; |
1007 | | #ifdef TVBPARSE_DEBUG |
1008 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) ws_warning("tvbparse_get: DONE offset=%i", tt->offset); |
1009 | | #endif |
1010 | 29.6k | return tok; |
1011 | 29.6k | } else { |
1012 | 4.37k | return NULL; |
1013 | 4.37k | } |
1014 | | |
1015 | 34.0k | } |
1016 | | |
1017 | | |
1018 | 0 | tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) { |
1019 | 0 | tvbparse_elem_t* tok = NULL; |
1020 | 0 | int len = 0; |
1021 | 0 | int offset = tt->offset; |
1022 | 0 | int target_offset = offset -1; |
1023 | |
|
1024 | | #ifdef TVBPARSE_DEBUG |
1025 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_warning("tvbparse_get: ENTER offset=%i", tt->offset); |
1026 | | #endif |
1027 | |
|
1028 | 0 | do { |
1029 | 0 | len = wanted->condition(tt, target_offset+1, wanted, &tok); |
1030 | 0 | } while(len < 0 && ++target_offset < tt->end_offset); |
1031 | |
|
1032 | 0 | if (len >= 0) { |
1033 | | #ifdef TVBPARSE_DEBUG |
1034 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len); |
1035 | | #endif |
1036 | 0 | execute_callbacks(tt,tok); |
1037 | 0 | tt->offset = target_offset + len; |
1038 | |
|
1039 | | #ifdef TVBPARSE_DEBUG |
1040 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_warning("tvbparse_get: DONE offset=%i", tt->offset); |
1041 | | #endif |
1042 | 0 | return tok; |
1043 | 0 | } else { |
1044 | | #ifdef TVBPARSE_DEBUG |
1045 | | if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) ws_warning("tvbparse_get: NOT FOUND"); |
1046 | | #endif |
1047 | 0 | return NULL; |
1048 | 0 | } |
1049 | 0 | } |
1050 | | |
1051 | | struct _elem_tree_stack_frame { |
1052 | | proto_tree* tree; |
1053 | | tvbparse_elem_t* elem; |
1054 | | }; |
1055 | | |
1056 | 154 | void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) { |
1057 | 154 | wmem_stack_t *stack = wmem_stack_new(curr->parser->scope); |
1058 | 154 | struct _elem_tree_stack_frame* frame = wmem_new(curr->parser->scope, struct _elem_tree_stack_frame); |
1059 | 154 | proto_item* pi; |
1060 | 154 | frame->tree = tree; |
1061 | 154 | frame->elem = curr; |
1062 | | |
1063 | 1.01k | while (curr) { |
1064 | 859 | pi = proto_tree_add_format_text(frame->tree,curr->parser->tvb,curr->offset,curr->len); |
1065 | | |
1066 | 859 | if(curr->sub) { |
1067 | 505 | frame->elem = curr; |
1068 | 505 | wmem_stack_push(stack, frame); |
1069 | 505 | frame = wmem_new(curr->parser->scope, struct _elem_tree_stack_frame); |
1070 | 505 | frame->tree = proto_item_add_subtree(pi,0); |
1071 | 505 | curr = curr->sub; |
1072 | 505 | continue; |
1073 | 505 | } |
1074 | | |
1075 | 354 | curr = curr->next; |
1076 | | |
1077 | 859 | while( !curr && wmem_stack_count(stack) > 0 ) { |
1078 | 505 | frame = (struct _elem_tree_stack_frame *)wmem_stack_pop(stack); |
1079 | 505 | curr = frame->elem->next; |
1080 | 505 | } |
1081 | | |
1082 | 354 | } |
1083 | 154 | } |
1084 | | |
1085 | | /* |
1086 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1087 | | * |
1088 | | * Local variables: |
1089 | | * c-basic-offset: 4 |
1090 | | * tab-width: 8 |
1091 | | * indent-tabs-mode: nil |
1092 | | * End: |
1093 | | * |
1094 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
1095 | | * :indentSize=4:tabSize=8:noTabs=true: |
1096 | | */ |