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
16 #include <wsutil/ws_assert.h>
18 typedef struct _mate_range mate_range
;
27 typedef struct _tmp_pdu_data
{
34 typedef struct _gogkey
{
40 static mate_runtime_data
* rd
;
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
);
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);
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
);
70 g_slice_free(mate_max_size
,(mate_max_size
*)gop
);
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);
85 g_ptr_array_free(gog
->gog_keys
, true);
88 g_slice_free(mate_max_size
,(mate_max_size
*)gog
);
93 static gboolean
return_true(void *k _U_
, void *v _U_
, void *p _U_
) {
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
);
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
);
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
);
125 void initialize_mate_runtime(mate_config
* mc
) {
127 dbg_print (dbg
,5,dbg_facility
,"initialize_mate: entering");
131 rd
= g_new(mate_runtime_data
, 1);
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;
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;
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");
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
);
169 dbg_print(dbg_gop
, 1, dbg_facility
, "new_gop: %s: ``%s:%d''", key
, gop
->cfg
->name
, gop
->id
);
172 gop
->avpl
= new_avpl(cfg
->name
);
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;
192 gop
->released
= false;
196 pdu
->is_start
= true;
197 pdu
->time_in_gop
= 0.0f
;
199 g_hash_table_insert(cfg
->gop_index
,gop
->gop_key
,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
);
209 if (gop
->cfg
->start
) {
210 gog
->num_of_counting_gops
++;
216 gog
->last_gop
->next
= 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
);
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
);
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
;
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();
258 static void apply_transforms(GPtrArray
* transforms
, AVPL
* avpl
) {
259 AVPL_Transf
* transform
= NULL
;
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) ;
274 merge_avpl(to
,our_extras
,true);
275 delete_avpl(our_extras
,false);
279 static void gog_remove_keys (mate_gog
* gog
) {
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
);
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
;
300 AVPL
* gogkey_match
= NULL
;
301 mate_gog
* gog
= gop
->gog
;
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
);
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 */
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
;
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
;
371 AVPL
* gogkey_match
= NULL
;
372 mate_gog
* gog
= NULL
;
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
);
382 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: no gog_keys for this gop");
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
);
409 dbg_print (dbg_gog
,1,dbg_facility
,"analyze_gop: this is our gog");
411 if (! gop
->gog
) adopt_gop(gog
,gop
);
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
);
421 gog
= new_gog(cfg
,gop
);
422 gog
->num_of_gops
= 1;
424 if (gop
->cfg
->start
) {
425 gog
->num_of_counting_gops
= 1;
429 dbg_print (dbg_gog
,0,dbg_facility
,"analyze_gop: no such gog_cfg: %s",curr_gogkey
->name
);
435 /** Can't get here because of "breaks" above */
436 ws_assert_not_reached();
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
) {
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
;
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
;
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
)) )
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
);
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
);
511 gop
= new_gop(cfg
,pdu
,gop_key
);
512 g_hash_table_insert(cfg
->gop_index
,gop_key
,gop
);
514 dbg_print (dbg_gop
,1,dbg_facility
,"analyze_pdu: duplicate start on gop");
521 if (gop
->last_pdu
) gop
->last_pdu
->next
= pdu
;
524 pdu
->time_in_gop
= rd
->now
- gop
->start_time
;
526 if (gop
->released
) pdu
->after_release
= true;
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
);
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);
553 delete_avpl(gogkey_match
,false);
561 delete_avpl(gopkey_match
,true);
567 delete_avpl(gopkey_match
,true);
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
);
586 if (gop
->last_pdu
) gop
->last_pdu
->next
= pdu
;
590 pdu
->time_in_gop
= rd
->now
- gop
->start_time
;
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);
612 is_stop
= new_avpl("");
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
++;
630 if (gop
->last_n
!= gop
->avpl
->len
) apply_transforms(gop
->cfg
->transforms
,gop
->avpl
);
632 gop
->last_n
= gop
->avpl
->len
;
635 reanalyze_gop(mc
, gop
);
637 analyze_gop(mc
, gop
);
641 dbg_print (dbg_gop
,4,dbg_facility
,"analyze_pdu: no match for this pdu");
648 // NOLINTNEXTLINE(misc-no-recursion)
649 proto_tree_find_node_from_finfo(proto_tree
*tree
, field_info
*finfo
)
651 proto_node
*pnode
= tree
;
655 if (PNODE_FINFO(pnode
) == finfo
) {
659 child
= pnode
->first_child
;
660 while (child
!= NULL
) {
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
))) {
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
678 add_avp(const char *name
, field_info
*fi
, const field_info
*ancestor_fi
, tmp_pdu_data
*data
)
682 mate_range
* curr_range
;
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
);
700 dbg_print(dbg_pdu
,0,dbg_facility
,"add_avp: got %s",s
);
704 if (! insert_avp(data
->pdu
->avpl
, avp
) ) {
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
;
728 fis
= proto_get_finfo_ptr_array(data
->tree
, hfid
);
731 for (i
= 0; i
< fis
->len
; i
++) {
732 fi
= (field_info
*) g_ptr_array_index(fis
,i
);
736 end
= fi
->start
+ fi
->length
;
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 */
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
);
771 mate_range
* proto_range
;
775 field_info
* range_fi
;
781 dbg_print (dbg_pdu
,1,dbg_facility
,"new_pdu: type=%s framenum=%i",cfg
->name
,framenum
);
783 pdu
->id
= ++(cfg
->last_id
);
786 pdu
->avpl
= new_avpl(cfg
->name
);
788 pdu
->frame
= framenum
;
789 pdu
->next_in_frame
= NULL
;
790 pdu
->rel_time
= rd
->now
;
794 pdu
->time_in_gop
= -1.0f
;
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
);
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
);
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
) ) {
828 min_dist
= last_start
- cfi
->start
;
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
);
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
);
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
) ) {
866 min_dist
= curr_end
- first_end
;
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
);
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);
897 extern void mate_analyze_frame(mate_config
*mc
, packet_info
*pinfo
, proto_tree
* tree
) {
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
++ ) {
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
);
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
);
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
);
958 if ( cfg
->discard
) {
959 delete_avpl(pdu
->avpl
,true);
964 g_hash_table_insert(rd
->frames
,GINT_TO_POINTER(pinfo
->num
),pdu
);
967 last
->next_in_frame
= 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
) {
984 return (mate_pdu
*) g_hash_table_lookup(rd
->frames
,GUINT_TO_POINTER(framenum
));
991 * Editor modelines - https://www.wireshark.org/tools/modelines.html
996 * indent-tabs-mode: t
999 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1000 * :indentSize=8:tabSize=8:noTabs=false: