regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / plugins / epan / mate / mate_runtime.c
blob0227dd45003efd2b528951684aacb22ea302df90
1 /* mate_runtime.c
2 * MATE -- Meta Analysis Tracing Engine
4 * Copyright 2004, Luis E. Garcia Ontanon <luis@ontanon.org>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include "mate.h"
16 #include <wsutil/ws_assert.h>
18 typedef struct _mate_range mate_range;
20 struct _mate_range {
21 tvbuff_t *ds_tvb;
22 unsigned start;
23 unsigned end;
27 typedef struct _tmp_pdu_data {
28 GPtrArray* ranges;
29 proto_tree* tree;
30 mate_pdu* pdu;
31 } tmp_pdu_data;
34 typedef struct _gogkey {
35 char* key;
36 mate_cfg_gop* cfg;
37 } gogkey;
40 static mate_runtime_data* rd;
42 static int zero = 5;
44 static int* dbg = &zero;
45 static int* dbg_pdu = &zero;
46 static int* dbg_gop = &zero;
47 static int* dbg_gog = &zero;
48 static FILE* dbg_facility;
50 static gboolean destroy_mate_pdus(void *k _U_, void *v, void *p _U_) {
51 mate_pdu* pdu = (mate_pdu*) v;
52 if (pdu->avpl) delete_avpl(pdu->avpl,true);
53 g_slice_free(mate_max_size, (mate_max_size *)pdu);
54 return TRUE;
57 static gboolean destroy_mate_gops(void *k _U_, void *v, void *p _U_) {
58 mate_gop* gop = (mate_gop*) v;
60 if (gop->avpl) delete_avpl(gop->avpl,true);
62 if (gop->gop_key) {
63 if (g_hash_table_lookup(gop->cfg->gop_index,gop->gop_key) == gop) {
64 g_hash_table_remove(gop->cfg->gop_index,gop->gop_key);
67 g_free(gop->gop_key);
70 g_slice_free(mate_max_size,(mate_max_size*)gop);
72 return TRUE;
76 static void gog_remove_keys (mate_gog* gog);
78 static gboolean destroy_mate_gogs(void *k _U_, void *v, void *p _U_) {
79 mate_gog* gog = (mate_gog*) v;
81 if (gog->avpl) delete_avpl(gog->avpl,true);
83 if (gog->gog_keys) {
84 gog_remove_keys(gog);
85 g_ptr_array_free(gog->gog_keys, true);
88 g_slice_free(mate_max_size,(mate_max_size*)gog);
90 return TRUE;
93 static gboolean return_true(void *k _U_, void *v _U_, void *p _U_) {
94 return TRUE;
97 static void destroy_pdus_in_cfg(void *k _U_, void *v, void *p _U_) {
98 mate_cfg_pdu* c = (mate_cfg_pdu *)v;
99 g_hash_table_foreach_remove(c->items,destroy_mate_pdus,NULL);
100 c->last_id = 0;
104 static void destroy_gops_in_cfg(void *k _U_, void *v, void *p _U_) {
105 mate_cfg_gop* c = (mate_cfg_gop *)v;
107 g_hash_table_foreach_remove(c->gop_index,return_true,NULL);
108 g_hash_table_destroy(c->gop_index);
109 c->gop_index = g_hash_table_new(g_str_hash,g_str_equal);
111 g_hash_table_foreach_remove(c->gog_index,return_true,NULL);
112 g_hash_table_destroy(c->gog_index);
113 c->gog_index = g_hash_table_new(g_str_hash,g_str_equal);
115 g_hash_table_foreach_remove(c->items,destroy_mate_gops,NULL);
116 c->last_id = 0;
119 static void destroy_gogs_in_cfg(void *k _U_, void *v, void *p _U_) {
120 mate_cfg_gog* c = (mate_cfg_gog *)v;
121 g_hash_table_foreach_remove(c->items,destroy_mate_gogs,NULL);
122 c->last_id = 0;
125 void initialize_mate_runtime(mate_config* mc) {
127 dbg_print (dbg,5,dbg_facility,"initialize_mate: entering");
129 if (mc) {
130 if (rd == NULL ) {
131 rd = g_new(mate_runtime_data, 1);
132 } else {
133 g_hash_table_foreach(mc->pducfgs,destroy_pdus_in_cfg,NULL);
134 g_hash_table_foreach(mc->gopcfgs,destroy_gops_in_cfg,NULL);
135 g_hash_table_foreach(mc->gogcfgs,destroy_gogs_in_cfg,NULL);
137 g_hash_table_destroy(rd->frames);
140 rd->current_items = 0;
141 rd->now = -1.0f;
142 rd->highest_analyzed_frame = 0;
143 rd->frames = g_hash_table_new(g_direct_hash,g_direct_equal);
146 /*mc->dbg_gop_lvl = 5;
147 mc->dbg_gog_lvl = 5;
149 dbg_pdu = &(mc->dbg_pdu_lvl);
150 dbg_gop = &(mc->dbg_gop_lvl);
151 dbg_gog = &(mc->dbg_gog_lvl);
152 dbg = &(mc->dbg_lvl);
153 dbg_facility = mc->dbg_facility;
155 dbg_print(dbg, 1, dbg_facility, "starting mate");
157 } else {
158 rd = NULL;
163 static mate_gop* new_gop(mate_cfg_gop* cfg, mate_pdu* pdu, char* key) {
164 mate_gop* gop = (mate_gop*)g_slice_new(mate_max_size);
166 gop->id = ++(cfg->last_id);
167 gop->cfg = cfg;
169 dbg_print(dbg_gop, 1, dbg_facility, "new_gop: %s: ``%s:%d''", key, gop->cfg->name, gop->id);
171 gop->gop_key = key;
172 gop->avpl = new_avpl(cfg->name);
173 gop->last_n = 0;
175 gop->gog = NULL;
176 gop->next = NULL;
178 gop->expiration = cfg->expiration > 0.0 ? cfg->expiration + rd->now : -1.0 ;
179 gop->idle_expiration = cfg->idle_timeout > 0.0 ? cfg->idle_timeout + rd->now : -1.0 ;
180 gop->time_to_die = cfg->lifetime > 0.0 ? cfg->lifetime + rd->now : -1.0 ;
181 gop->time_to_timeout = 0.0f;
183 gop->last_time = gop->start_time = rd->now;
184 gop->release_time = 0.0f;
186 gop->num_of_pdus = 0;
187 gop->num_of_after_release_pdus = 0;
189 gop->pdus = pdu;
190 gop->last_pdu = pdu;
192 gop->released = false;
194 pdu->gop = gop;
195 pdu->next = NULL;
196 pdu->is_start = true;
197 pdu->time_in_gop = 0.0f;
199 g_hash_table_insert(cfg->gop_index,gop->gop_key,gop);
200 return gop;
203 static void adopt_gop(mate_gog* gog, mate_gop* gop) {
204 dbg_print (dbg_gog,5,dbg_facility,"adopt_gop: gog=%p gop=%p",(void*)gog,(void*)gop);
206 gop->gog = gog;
207 gop->next = NULL;
209 if (gop->cfg->start) {
210 gog->num_of_counting_gops++;
213 gog->num_of_gops++;
215 if (gog->last_gop) {
216 gog->last_gop->next = gop;
219 gog->last_gop = gop;
221 if (! gog->gops ) {
222 gog->gops = gop;
227 static mate_gog* new_gog(mate_cfg_gog* cfg, mate_gop* gop) {
228 mate_gog* gog = (mate_gog*)g_slice_new(mate_max_size);
229 gog->id = ++(cfg->last_id);
230 gog->cfg = cfg;
232 dbg_print (dbg_gog,1,dbg_facility,"new_gog: %s:%u for %s:%u",gog->cfg->name,gog->id,gop->cfg->name,gop->id);
234 gog->avpl = new_avpl(cfg->name);
235 gog->last_n = 0;
237 gog->expiration = 0.0f;
238 gog->idle_expiration = 0.0f;
240 gog->start_time = rd->now;
241 gog->release_time = 0.0f;
242 gog->last_time = 0.0f;
244 gog->gops = NULL;
245 gog->last_gop = NULL;
247 gog->num_of_gops = 0;
248 gog->num_of_counting_gops = 0;
249 gog->num_of_released_gops = 0;
251 gog->gog_keys = g_ptr_array_new();
253 adopt_gop(gog,gop);
255 return gog;
258 static void apply_transforms(GPtrArray* transforms, AVPL* avpl) {
259 AVPL_Transf* transform = NULL;
260 unsigned i;
262 for (i = 0; i < transforms->len; i++) {
263 transform = (AVPL_Transf *)g_ptr_array_index(transforms,i);
264 avpl_transform(avpl, transform);
269 /* applies the extras for which type to what avpl */
270 static void apply_extras(AVPL* from, AVPL* to, AVPL* extras) {
271 AVPL* our_extras = new_avpl_loose_match("",from, extras, false) ;
273 if (our_extras) {
274 merge_avpl(to,our_extras,true);
275 delete_avpl(our_extras,false);
279 static void gog_remove_keys (mate_gog* gog) {
280 gogkey* gog_key;
282 while (gog->gog_keys->len) {
283 gog_key = (gogkey *)g_ptr_array_remove_index_fast(gog->gog_keys,0);
285 if (g_hash_table_lookup(gog_key->cfg->gog_index,gog_key->key) == gog) {
286 g_hash_table_remove(gog_key->cfg->gog_index,gog_key->key);
289 g_free(gog_key->key);
290 g_free(gog_key);
295 static void reanalyze_gop(mate_config* mc, mate_gop* gop) {
296 LoAL* gog_keys = NULL;
297 AVPL* curr_gogkey = NULL;
298 mate_cfg_gop* gop_cfg = NULL;
299 void* cookie = NULL;
300 AVPL* gogkey_match = NULL;
301 mate_gog* gog = gop->gog;
302 gogkey* gog_key;
304 if ( ! gog ) return;
306 gog->last_time = rd->now;
308 dbg_print (dbg_gog,1,dbg_facility,"reanalyze_gop: %s:%d",gop->cfg->name,gop->id);
310 apply_extras(gop->avpl,gog->avpl,gog->cfg->extra);
312 /* XXX: Instead of using the length of the avpl to check if an avpl has changed,
313 which is not accurate at all, we should have apply_extras,
314 apply_transformations and other functions that can modify the avpl
315 to flag the avpl if it has changed, then we'll check for the flag
316 and clear it after analysis */
318 if (gog->last_n != gog->avpl->len) {
320 dbg_print (dbg_gog,2,dbg_facility,"reanalyze_gop: gog has new attributes let's look for new keys");
322 gog_keys = gog->cfg->keys;
324 while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) {
325 gop_cfg = (mate_cfg_gop *)g_hash_table_lookup(mc->gopcfgs,curr_gogkey->name);
327 if (( gogkey_match = new_avpl_pairs_match(gop_cfg->name, gog->avpl, curr_gogkey, true, false) )) {
329 gog_key = g_new(gogkey, 1);
331 gog_key->key = avpl_to_str(gogkey_match);
332 delete_avpl(gogkey_match,false);
334 gog_key->cfg = gop_cfg;
336 if (g_hash_table_lookup(gop_cfg->gog_index,gog_key->key)) {
337 g_free(gog_key->key);
338 g_free(gog_key);
339 gog_key = NULL;
342 if (! gog_key ) {
343 /* XXX: since these gogs actually share key info
344 we should try to merge (non released) gogs
345 that happen to have equal keys */
346 } else {
347 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: new key for gog=%s:%d : %s",gog->cfg->name,gog->id,gog_key->key);
348 g_ptr_array_add(gog->gog_keys,gog_key);
349 g_hash_table_insert(gog_key->cfg->gog_index,gog_key->key,gog);
355 gog->last_n = gog->avpl->len;
358 if (gog->num_of_released_gops == gog->num_of_counting_gops) {
359 gog->released = true;
360 gog->expiration = gog->cfg->expiration + rd->now;
361 } else {
362 gog->released = false;
366 static void analyze_gop(mate_config* mc, mate_gop* gop) {
367 mate_cfg_gog* cfg = NULL;
368 LoAL* gog_keys = NULL;
369 AVPL* curr_gogkey = NULL;
370 void* cookie = NULL;
371 AVPL* gogkey_match = NULL;
372 mate_gog* gog = NULL;
373 char* key = NULL;
375 if ( ! gop->gog ) {
376 /* no gog, let's either find one or create it if due */
377 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no gog");
379 gog_keys = (LoAL *)g_hash_table_lookup(mc->gogs_by_gopname,gop->cfg->name);
381 if ( ! gog_keys ) {
382 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no gog_keys for this gop");
383 return;
386 /* We have gog_keys! look for matching gogkeys */
388 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got gog_keys: %s",gog_keys->name) ;
390 while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) {
391 if (( gogkey_match = new_avpl_pairs_match(gop->cfg->name, gop->avpl, curr_gogkey, true, true) )) {
393 key = avpl_to_str(gogkey_match);
395 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got gogkey_match: %s",key);
397 if (( gog = (mate_gog *)g_hash_table_lookup(gop->cfg->gog_index,key) )) {
398 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got already a matching gog: %s:%d",gog->cfg->name,gog->id);
400 if (gog->num_of_counting_gops == gog->num_of_released_gops && gog->expiration < rd->now) {
401 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: this is a new gog, not the old one, let's create it");
403 gog_remove_keys(gog);
405 new_gog(gog->cfg,gop);
407 break;
408 } else {
409 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: this is our gog");
411 if (! gop->gog ) adopt_gop(gog,gop);
413 break;
415 } else {
416 dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no such gog in hash, let's create a new %s",curr_gogkey->name);
418 cfg = (mate_cfg_gog *)g_hash_table_lookup(mc->gogcfgs,curr_gogkey->name);
420 if (cfg) {
421 gog = new_gog(cfg,gop);
422 gog->num_of_gops = 1;
424 if (gop->cfg->start) {
425 gog->num_of_counting_gops = 1;
428 } else {
429 dbg_print (dbg_gog,0,dbg_facility,"analyze_gop: no such gog_cfg: %s",curr_gogkey->name);
432 break;
435 /** Can't get here because of "breaks" above */
436 ws_assert_not_reached();
438 } /* while */
440 g_free(key);
441 key = NULL;
443 if (gogkey_match) delete_avpl(gogkey_match,true);
445 reanalyze_gop(mc, gop);
451 static void analyze_pdu(mate_config* mc, mate_pdu* pdu) {
452 /* TODO:
453 return a g_boolean to tell we've destroyed the pdu when the pdu is unnassigned
454 destroy the unassigned pdu
456 mate_cfg_gop* cfg = NULL;
457 mate_gop* gop = NULL;
458 char* gop_key;
459 char* orig_gop_key = NULL;
460 AVPL* candidate_start = NULL;
461 AVPL* candidate_stop = NULL;
462 AVPL* is_start = NULL;
463 AVPL* is_stop = NULL;
464 AVPL* gopkey_match = NULL;
465 LoAL* gog_keys = NULL;
466 AVPL* curr_gogkey = NULL;
467 void* cookie = NULL;
468 AVPL* gogkey_match = NULL;
469 char* gogkey_str = NULL;
471 dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: %s",pdu->cfg->name);
473 if (! (cfg = (mate_cfg_gop *)g_hash_table_lookup(mc->gops_by_pduname,pdu->cfg->name)) )
474 return;
476 if ((gopkey_match = new_avpl_pairs_match("gop_key_match", pdu->avpl, cfg->key, true, true))) {
477 gop_key = avpl_to_str(gopkey_match);
479 g_hash_table_lookup_extended(cfg->gop_index,(const void *)gop_key,(void * *)&orig_gop_key,(void * *)&gop);
481 if ( gop ) {
482 g_free(gop_key);
484 /* is the gop dead ? */
485 if ( ! gop->released &&
486 ( ( gop->cfg->lifetime > 0.0 && gop->time_to_die >= rd->now) ||
487 ( gop->cfg->idle_timeout > 0.0 && gop->time_to_timeout >= rd->now) ) ) {
488 dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: expiring released gop");
489 gop->released = true;
491 if (gop->gog && gop->cfg->start) gop->gog->num_of_released_gops++;
494 /* TODO: is the gop expired? */
496 gop_key = orig_gop_key;
498 dbg_print (dbg_gop,2,dbg_facility,"analyze_pdu: got gop: %s",gop_key);
500 if (( candidate_start = cfg->start )) {
502 dbg_print (dbg_gop,2,dbg_facility,"analyze_pdu: got candidate start");
504 if (( is_start = new_avpl_pairs_match("", pdu->avpl, candidate_start, true, false) )) {
505 delete_avpl(is_start,false);
506 if ( gop->released ) {
507 dbg_print (dbg_gop,3,dbg_facility,"analyze_pdu: start on released gop, let's create a new gop");
509 g_hash_table_remove(cfg->gop_index,gop_key);
510 gop->gop_key = NULL;
511 gop = new_gop(cfg,pdu,gop_key);
512 g_hash_table_insert(cfg->gop_index,gop_key,gop);
513 } else {
514 dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: duplicate start on gop");
519 pdu->gop = gop;
521 if (gop->last_pdu) gop->last_pdu->next = pdu;
522 gop->last_pdu = pdu;
523 pdu->next = NULL;
524 pdu->time_in_gop = rd->now - gop->start_time;
526 if (gop->released) pdu->after_release = true;
528 } else {
530 dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: no gop already");
532 if ( ! cfg->start ) {
533 /* there is no GopStart, we'll check for matching GogKeys
534 if we have one we'll create the Gop */
536 apply_extras(pdu->avpl,gopkey_match,cfg->extra);
538 gog_keys = (LoAL *)g_hash_table_lookup(mc->gogs_by_gopname,cfg->name);
540 if (gog_keys) {
542 while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) {
543 if (( gogkey_match = new_avpl_pairs_match(cfg->name, gopkey_match, curr_gogkey, true, false) )) {
544 gogkey_str = avpl_to_str(gogkey_match);
546 if (g_hash_table_lookup(cfg->gog_index,gogkey_str)) {
547 gop = new_gop(cfg,pdu,gop_key);
548 g_hash_table_insert(cfg->gop_index,gop_key,gop);
549 delete_avpl(gogkey_match,false);
550 g_free(gogkey_str);
551 break;
552 } else {
553 delete_avpl(gogkey_match,false);
554 g_free(gogkey_str);
559 if ( ! gop ) {
560 g_free(gop_key);
561 delete_avpl(gopkey_match,true);
562 return;
565 } else {
566 g_free(gop_key);
567 delete_avpl(gopkey_match,true);
568 return;
571 } else {
572 candidate_start = cfg->start;
574 if (( is_start = new_avpl_pairs_match("", pdu->avpl, candidate_start, true, false) )) {
575 delete_avpl(is_start,false);
576 gop = new_gop(cfg,pdu,gop_key);
577 } else {
578 g_free(gop_key);
579 return;
582 pdu->gop = gop;
586 if (gop->last_pdu) gop->last_pdu->next = pdu;
587 gop->last_pdu = pdu;
588 pdu->next = NULL;
590 pdu->time_in_gop = rd->now - gop->start_time;
592 gop->num_of_pdus++;
593 gop->time_to_timeout = cfg->idle_timeout > 0.0 ? cfg->idle_timeout + rd->now : -1.0 ;
595 dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: merge with key");
597 merge_avpl(gop->avpl,gopkey_match,true);
598 delete_avpl(gopkey_match,true);
600 dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: apply extras");
602 apply_extras(pdu->avpl,gop->avpl,gop->cfg->extra);
604 gop->last_time = pdu->rel_time;
606 if ( ! gop->released) {
607 candidate_stop = cfg->stop;
609 if (candidate_stop) {
610 is_stop = new_avpl_pairs_match("", pdu->avpl, candidate_stop, true, false);
611 } else {
612 is_stop = new_avpl("");
615 if(is_stop) {
616 dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: is a `stop");
617 delete_avpl(is_stop,false);
619 if (! gop->released) {
620 gop->released = true;
621 gop->release_time = pdu->rel_time;
622 if (gop->gog && gop->cfg->start) gop->gog->num_of_released_gops++;
625 pdu->is_stop = true;
630 if (gop->last_n != gop->avpl->len) apply_transforms(gop->cfg->transforms,gop->avpl);
632 gop->last_n = gop->avpl->len;
634 if (gop->gog) {
635 reanalyze_gop(mc, gop);
636 } else {
637 analyze_gop(mc, gop);
640 } else {
641 dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: no match for this pdu");
643 pdu->gop = NULL;
647 static proto_node *
648 // NOLINTNEXTLINE(misc-no-recursion)
649 proto_tree_find_node_from_finfo(proto_tree *tree, field_info *finfo)
651 proto_node *pnode = tree;
652 proto_node *child;
653 proto_node *current;
655 if (PNODE_FINFO(pnode) == finfo) {
656 return pnode;
659 child = pnode->first_child;
660 while (child != NULL) {
661 current = child;
662 child = current->next;
663 // We recurse here, but we're limited by tree depth checks in epan
664 if ((pnode = proto_tree_find_node_from_finfo((proto_tree *)current, finfo))) {
665 return pnode;
669 return NULL;
672 /* This returns true if there's no point in searching for the avp among the
673 * ancestor nodes in the tree. That includes if the field is within one
674 * of the ranges, or if the field and all the ranges share the same
675 * data source.
677 static bool
678 add_avp(const char *name, field_info *fi, const field_info *ancestor_fi, tmp_pdu_data *data)
680 AVP* avp;
681 char* s;
682 mate_range* curr_range;
683 unsigned start, end;
684 tvbuff_t *ds_tvb;
685 bool all_same_ds = true;
687 start = ancestor_fi->start;
688 end = ancestor_fi->start + ancestor_fi->length;
689 ds_tvb = ancestor_fi->ds_tvb;
691 for (unsigned j = 0; j < data->ranges->len; j++) {
693 curr_range = (mate_range*) g_ptr_array_index(data->ranges,j);
695 if (curr_range->ds_tvb == ds_tvb) {
696 if (curr_range->end >= end && curr_range->start <= start) {
697 avp = new_avp_from_finfo(name, fi);
698 if (*dbg_pdu > 4) {
699 s = avp_to_str(avp);
700 dbg_print(dbg_pdu,0,dbg_facility,"add_avp: got %s",s);
701 g_free(s);
704 if (! insert_avp(data->pdu->avpl, avp) ) {
705 delete_avp(avp);
707 return true;
709 } else {
710 all_same_ds = false;
714 return all_same_ds;
717 static void get_pdu_fields(void *k, void *v, void *p) {
718 int hfid = *((int*) k);
719 char* name = (char*) v;
720 tmp_pdu_data* data = (tmp_pdu_data*) p;
721 GPtrArray* fis;
722 field_info* fi;
723 unsigned i;
724 unsigned start;
725 unsigned end;
726 tvbuff_t *ds_tvb;
728 fis = proto_get_finfo_ptr_array(data->tree, hfid);
730 if (fis) {
731 for (i = 0; i < fis->len; i++) {
732 fi = (field_info*) g_ptr_array_index(fis,i);
735 start = fi->start;
736 end = fi->start + fi->length;
737 ds_tvb = fi->ds_tvb;
739 dbg_print(dbg_pdu,5,dbg_facility,"get_pdu_fields: found field %s, %i-%i, length %i", fi->hfinfo->abbrev, start, end, fi->length);
741 if (!add_avp(name, fi, fi, data)) {
742 /* The field came from a different data source than one of the
743 * ranges (protocol, transport protocol, payload). Search for
744 * the tree node with the field and look to see if one of its
745 * parents is contained within one of the ranges.
746 * (The field, and the hfis for the ranges, were marked as
747 * interesting so this should always work, albeit slower than above.)
749 for (proto_node *pnode = proto_tree_find_node_from_finfo(data->tree, fi);
750 pnode; pnode = pnode->parent) {
751 field_info *ancestor_fi = PNODE_FINFO(pnode);
752 if (ancestor_fi && ancestor_fi->ds_tvb != ds_tvb) {
753 /* Only check anew when the data source changes. */
754 ds_tvb = ancestor_fi->ds_tvb;
755 if (add_avp(name, fi, ancestor_fi, data)) {
756 /* Go to next field in fis */
757 break;
766 static mate_pdu* new_pdu(mate_cfg_pdu* cfg, uint32_t framenum, field_info* proto, proto_tree* tree) {
767 mate_pdu* pdu = (mate_pdu*)g_slice_new(mate_max_size);
768 field_info* cfi;
769 GPtrArray* ptrs;
770 mate_range* range;
771 mate_range* proto_range;
772 tmp_pdu_data data;
773 unsigned i,j;
774 int min_dist;
775 field_info* range_fi;
776 int32_t last_start;
777 int32_t first_end;
778 int32_t curr_end;
779 int hfid;
781 dbg_print (dbg_pdu,1,dbg_facility,"new_pdu: type=%s framenum=%i",cfg->name,framenum);
783 pdu->id = ++(cfg->last_id);
784 pdu->cfg = cfg;
786 pdu->avpl = new_avpl(cfg->name);
788 pdu->frame = framenum;
789 pdu->next_in_frame = NULL;
790 pdu->rel_time = rd->now;
792 pdu->gop = NULL;
793 pdu->next = NULL;
794 pdu->time_in_gop = -1.0f;
796 pdu->first = false;
797 pdu->is_start = false;
798 pdu->is_stop = false;
799 pdu->after_release = false;
801 data.ranges = g_ptr_array_new_with_free_func(g_free);
802 data.pdu = pdu;
803 data.tree = tree;
805 /* first we create the proto range */
806 proto_range = g_new(mate_range, 1);
807 proto_range->ds_tvb = proto->ds_tvb;
808 proto_range->start = proto->start;
809 proto_range->end = proto->start + proto->length;
810 g_ptr_array_add(data.ranges,proto_range);
812 dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: proto range %u-%u",proto_range->start,proto_range->end);
814 last_start = proto_range->start;
816 /* we move forward in the transport */
817 for (i = cfg->transport_ranges->len; i--; ) {
818 hfid = *((int*)g_ptr_array_index(cfg->transport_ranges,i));
819 ptrs = proto_get_finfo_ptr_array(tree, hfid);
820 min_dist = 99999;
821 range_fi = NULL;
823 if (ptrs) {
824 for (j=0; j < ptrs->len; j++) {
825 cfi = (field_info*) g_ptr_array_index(ptrs,j);
826 if (cfi->start < last_start && min_dist >= (last_start - cfi->start) ) {
827 range_fi = cfi;
828 min_dist = last_start - cfi->start;
832 if ( range_fi ) {
833 range = (mate_range *)g_malloc(sizeof(*range));
834 range->ds_tvb = range_fi->ds_tvb;
835 range->start = range_fi->start;
836 range->end = range_fi->start + range_fi->length;
837 g_ptr_array_add(data.ranges,range);
839 last_start = range_fi->start;
841 dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: transport(%i) range %i-%i",hfid,range->start,range->end);
842 } else {
843 /* we missed a range */
844 dbg_print(dbg_pdu,6,dbg_facility,"new_pdu: transport(%i) missed",hfid);
850 if (cfg->payload_ranges) {
852 first_end = proto_range->end;
854 for (i = 0 ; i < cfg->payload_ranges->len; i++) {
855 hfid = *((int*)g_ptr_array_index(cfg->payload_ranges,i));
856 ptrs = proto_get_finfo_ptr_array(tree, hfid);
857 min_dist = 99999;
858 range_fi = NULL;
860 if (ptrs) {
861 for (j=0; j < ptrs->len; j++) {
862 cfi = (field_info*) g_ptr_array_index(ptrs,j);
863 curr_end = cfi->start + cfi->length;
864 if (curr_end > first_end && min_dist >= (curr_end - first_end) ) {
865 range_fi = cfi;
866 min_dist = curr_end - first_end;
870 if ( range_fi ) {
871 range = (mate_range *)g_malloc(sizeof(*range));
872 range->ds_tvb = range_fi->ds_tvb;
873 range->start = range_fi->start;
874 range->end = range_fi->start + range_fi->length;
875 g_ptr_array_add(data.ranges,range);
877 dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: payload(%i) range %i-%i",hfid,range->start,range->end);
878 } else {
879 /* we missed a range */
880 dbg_print(dbg_pdu,5,dbg_facility,"new_pdu: payload(%i) missed",hfid);
887 g_hash_table_foreach(cfg->hfids_attr,get_pdu_fields,&data);
889 apply_transforms(pdu->cfg->transforms,pdu->avpl);
891 g_ptr_array_free(data.ranges,true);
893 return pdu;
897 extern void mate_analyze_frame(mate_config *mc, packet_info *pinfo, proto_tree* tree) {
898 mate_cfg_pdu* cfg;
899 GPtrArray* protos;
900 field_info* proto;
901 unsigned i,j;
902 AVPL* criterium_match;
904 mate_pdu* pdu = NULL;
905 mate_pdu* last = NULL;
907 rd->now = nstime_to_sec(&pinfo->rel_ts);
909 if ( proto_tracking_interesting_fields(tree)
910 && rd->highest_analyzed_frame < pinfo->num ) {
911 for ( i = 0; i < mc->pducfglist->len; i++ ) {
913 if (i == 0) {
914 dbg_print (dbg_pdu,4,dbg_facility,"\nmate_analyze_frame: frame: %i",pinfo->num);
916 cfg = (mate_cfg_pdu *)g_ptr_array_index(mc->pducfglist,i);
918 dbg_print (dbg_pdu,4,dbg_facility,"mate_analyze_frame: trying to extract: %s",cfg->name);
919 protos = proto_get_finfo_ptr_array(tree, cfg->hfid_proto);
921 if (protos) {
922 pdu = NULL;
924 for (j = 0; j < protos->len; j++) {
926 dbg_print (dbg_pdu,3,dbg_facility,"mate_analyze_frame: found matching proto, extracting: %s",cfg->name);
928 proto = (field_info*) g_ptr_array_index(protos,j);
929 pdu = new_pdu(cfg, pinfo->num, proto, tree);
931 if (cfg->criterium) {
932 criterium_match = new_avpl_from_match(cfg->criterium_match_mode,"",pdu->avpl,cfg->criterium,false);
934 if (criterium_match) {
935 delete_avpl(criterium_match,false);
938 if ( (criterium_match && cfg->criterium_accept_mode == REJECT_MODE )
939 || ( ! criterium_match && cfg->criterium_accept_mode == ACCEPT_MODE )) {
941 delete_avpl(pdu->avpl,true);
942 g_slice_free(mate_max_size,(mate_max_size*)pdu);
943 pdu = NULL;
945 continue;
949 analyze_pdu(mc, pdu);
951 if ( ! pdu->gop && cfg->drop_unassigned) {
952 delete_avpl(pdu->avpl,true);
953 g_slice_free(mate_max_size,(mate_max_size*)pdu);
954 pdu = NULL;
955 continue;
958 if ( cfg->discard ) {
959 delete_avpl(pdu->avpl,true);
960 pdu->avpl = NULL;
963 if (!last) {
964 g_hash_table_insert(rd->frames,GINT_TO_POINTER(pinfo->num),pdu);
965 last = pdu;
966 } else {
967 last->next_in_frame = pdu;
968 last = pdu;
973 if ( pdu && cfg->last_extracted ) break;
977 rd->highest_analyzed_frame = pinfo->num;
981 extern mate_pdu* mate_get_pdus(uint32_t framenum) {
983 if (rd) {
984 return (mate_pdu*) g_hash_table_lookup(rd->frames,GUINT_TO_POINTER(framenum));
985 } else {
986 return NULL;
991 * Editor modelines - https://www.wireshark.org/tools/modelines.html
993 * Local variables:
994 * c-basic-offset: 8
995 * tab-width: 8
996 * indent-tabs-mode: t
997 * End:
999 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1000 * :indentSize=8:tabSize=8:noTabs=false: