diff options
Diffstat (limited to 'plugins/epan/mate/mate_runtime.c')
-rw-r--r-- | plugins/epan/mate/mate_runtime.c | 936 |
1 files changed, 936 insertions, 0 deletions
diff --git a/plugins/epan/mate/mate_runtime.c b/plugins/epan/mate/mate_runtime.c new file mode 100644 index 0000000000..82c7af26ea --- /dev/null +++ b/plugins/epan/mate/mate_runtime.c @@ -0,0 +1,936 @@ +/* mate_runtime.c +* MATE -- Meta Analysis Tracing Engine +* +* Copyright 2004, Luis E. Garcia Ontanon <luis@ontanon.org> +* +* Wireshark - Network traffic analyzer +* By Gerald Combs <gerald@wireshark.org> +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "mate.h" + +typedef struct _mate_range mate_range; + +struct _mate_range { + guint start; + guint end; +}; + + +typedef struct _tmp_pdu_data { + GPtrArray* ranges; + proto_tree* tree; + mate_pdu* pdu; +} tmp_pdu_data; + + +typedef struct _gogkey { + gchar* key; + mate_cfg_gop* cfg; +} gogkey; + + +static mate_runtime_data* rd = NULL; + +static int zero = 5; + +static int* dbg = &zero; +static int* dbg_pdu = &zero; +static int* dbg_gop = &zero; +static int* dbg_gog = &zero; +static FILE* dbg_facility = NULL; + +static gboolean destroy_mate_pdus(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_pdu* pdu = (mate_pdu*) v; + if (pdu->avpl) delete_avpl(pdu->avpl,TRUE); + g_slice_free(mate_max_size, (mate_max_size *)pdu); + return TRUE; +} + +static gboolean destroy_mate_gops(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_gop* gop = (mate_gop*) v; + + if (gop->avpl) delete_avpl(gop->avpl,TRUE); + + if (gop->gop_key) { + if (g_hash_table_lookup(gop->cfg->gop_index,gop->gop_key) == gop) { + g_hash_table_remove(gop->cfg->gop_index,gop->gop_key); + } + + g_free(gop->gop_key); + } + + g_slice_free(mate_max_size,(mate_max_size*)gop); + + return TRUE; +} + + +static void gog_remove_keys (mate_gog* gog); + +static gboolean destroy_mate_gogs(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_gog* gog = (mate_gog*) v; + + if (gog->avpl) delete_avpl(gog->avpl,TRUE); + + if (gog->gog_keys) { + gog_remove_keys(gog); + g_ptr_array_free(gog->gog_keys,FALSE); + } + + g_slice_free(mate_max_size,(mate_max_size*)gog); + + return TRUE; +} + +static gboolean return_true(gpointer k _U_, gpointer v _U_, gpointer p _U_) { + return TRUE; +} + +static void destroy_pdus_in_cfg(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_pdu* c = (mate_cfg_pdu *)v; + g_hash_table_foreach_remove(c->items,destroy_mate_pdus,NULL); + c->last_id = 0; +} + + +static void destroy_gops_in_cfg(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_gop* c = (mate_cfg_gop *)v; + + g_hash_table_foreach_remove(c->gop_index,return_true,NULL); + g_hash_table_destroy(c->gop_index); + c->gop_index = g_hash_table_new(g_str_hash,g_str_equal); + + g_hash_table_foreach_remove(c->gog_index,return_true,NULL); + g_hash_table_destroy(c->gog_index); + c->gog_index = g_hash_table_new(g_str_hash,g_str_equal); + + g_hash_table_foreach_remove(c->items,destroy_mate_gops,NULL); + c->last_id = 0; +} + +static void destroy_gogs_in_cfg(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_gog* c = (mate_cfg_gog *)v; + g_hash_table_foreach_remove(c->items,destroy_mate_gogs,NULL); + c->last_id = 0; +} + +void initialize_mate_runtime(mate_config* mc) { + + dbg_print (dbg,5,dbg_facility,"initialize_mate: entering"); + + if (mc) { + if (rd == NULL ) { + rd = (mate_runtime_data *)g_malloc(sizeof(mate_runtime_data)); + } else { + g_hash_table_foreach(mc->pducfgs,destroy_pdus_in_cfg,NULL); + g_hash_table_foreach(mc->gopcfgs,destroy_gops_in_cfg,NULL); + g_hash_table_foreach(mc->gogcfgs,destroy_gogs_in_cfg,NULL); + + g_hash_table_destroy(rd->frames); + } + + rd->current_items = 0; + rd->now = -1.0f; + rd->highest_analyzed_frame = 0; + rd->frames = g_hash_table_new(g_direct_hash,g_direct_equal); + + + /*mc->dbg_gop_lvl = 5; + mc->dbg_gog_lvl = 5; + */ + dbg_pdu = &(mc->dbg_pdu_lvl); + dbg_gop = &(mc->dbg_gop_lvl); + dbg_gog = &(mc->dbg_gog_lvl); + dbg = &(mc->dbg_lvl); + dbg_facility = mc->dbg_facility; + + dbg_print(dbg, 1, dbg_facility, "starting mate"); + + } else { + rd = NULL; + } +} + + +static mate_gop* new_gop(mate_cfg_gop* cfg, mate_pdu* pdu, gchar* key) { + mate_gop* gop = (mate_gop*)g_slice_new(mate_max_size); + + gop->id = ++(cfg->last_id); + gop->cfg = cfg; + + dbg_print(dbg_gop, 1, dbg_facility, "new_gop: %s: ``%s:%d''", key, gop->cfg->name, gop->id); + + gop->gop_key = key; + gop->avpl = new_avpl(cfg->name); + gop->last_n = 0; + + gop->gog = NULL; + gop->next = NULL; + + gop->expiration = cfg->expiration > 0.0 ? cfg->expiration + rd->now : (float) -1.0 ; + gop->idle_expiration = cfg->idle_timeout > 0.0 ? cfg->idle_timeout + rd->now : (float) -1.0 ; + gop->time_to_die = cfg->lifetime > 0.0 ? cfg->lifetime + rd->now : (float) -1.0 ; + gop->time_to_timeout = 0.0f; + + gop->last_time = gop->start_time = rd->now; + gop->release_time = 0.0f; + + gop->num_of_pdus = 0; + gop->num_of_after_release_pdus = 0; + + gop->pdus = pdu; + gop->last_pdu = pdu; + + gop->released = FALSE; + + pdu->gop = gop; + pdu->next = NULL; + pdu->is_start = TRUE; + pdu->time_in_gop = 0.0f; + + g_hash_table_insert(cfg->gop_index,gop->gop_key,gop); + return gop; +} + +static void adopt_gop(mate_gog* gog, mate_gop* gop) { + dbg_print (dbg_gog,5,dbg_facility,"adopt_gop: gog=%p gop=%p",(void*)gog,(void*)gop); + + gop->gog = gog; + gop->next = NULL; + + if (gop->cfg->start) { + gog->num_of_counting_gops++; + } + + gog->num_of_gops++; + + if (gog->last_gop) { + gog->last_gop->next = gop; + } + + gog->last_gop = gop; + + if (! gog->gops ) { + gog->gops = gop; + } + +} + +static mate_gog* new_gog(mate_cfg_gog* cfg, mate_gop* gop) { + mate_gog* gog = (mate_gog*)g_slice_new(mate_max_size); + gog->id = ++(cfg->last_id); + gog->cfg = cfg; + + dbg_print (dbg_gog,1,dbg_facility,"new_gog: %s:%u for %s:%u",gog->cfg->name,gog->id,gop->cfg->name,gop->id); + + gog->avpl = new_avpl(cfg->name); + gog->last_n = 0; + + gog->expiration = 0.0f; + gog->idle_expiration = 0.0f; + + gog->start_time = rd->now; + gog->release_time = 0.0f; + gog->last_time = 0.0f; + + gog->gops = NULL; + gog->last_gop = NULL; + + gog->num_of_gops = 0; + gog->num_of_counting_gops = 0; + gog->num_of_released_gops = 0; + + gog->gog_keys = g_ptr_array_new(); + + adopt_gop(gog,gop); + + return gog; +} + +static void apply_transforms(GPtrArray* transforms, AVPL* avpl) { + AVPL_Transf* transform = NULL; + guint i; + + for (i = 0; i < transforms->len; i++) { + transform = (AVPL_Transf *)g_ptr_array_index(transforms,i); + avpl_transform(avpl, transform); + } +} + + +/* applies the extras for which type to what avpl */ +static void apply_extras(AVPL* from, AVPL* to, AVPL* extras) { + AVPL* our_extras = new_avpl_loose_match("",from, extras, FALSE) ; + + if (our_extras) { + merge_avpl(to,our_extras,TRUE); + delete_avpl(our_extras,FALSE); + } +} + +static void gog_remove_keys (mate_gog* gog) { + gogkey* gog_key; + + while (gog->gog_keys->len) { + gog_key = (gogkey *)g_ptr_array_remove_index_fast(gog->gog_keys,0); + + if (g_hash_table_lookup(gog_key->cfg->gog_index,gog_key->key) == gog) { + g_hash_table_remove(gog_key->cfg->gog_index,gog_key->key); + } + + g_free(gog_key->key); + g_free(gog_key); + } + +} + +static void reanalyze_gop(mate_config* mc, mate_gop* gop) { + LoAL* gog_keys = NULL; + AVPL* curr_gogkey = NULL; + mate_cfg_gop* gop_cfg = NULL; + void* cookie = NULL; + AVPL* gogkey_match = NULL; + mate_gog* gog = gop->gog; + gogkey* gog_key; + + if ( ! gog ) return; + + gog->last_time = rd->now; + + dbg_print (dbg_gog,1,dbg_facility,"reanalyze_gop: %s:%d",gop->cfg->name,gop->id); + + apply_extras(gop->avpl,gog->avpl,gog->cfg->extra); + + /* XXX: Instead of using the length of the avpl to check if an avpl has changed, + which is not accurate at all, we should have apply_extras, + apply_transformations and other functions that can modify the avpl + to flag the avpl if it has changed, then we'll check for the flag + and clear it after analysis */ + + if (gog->last_n != gog->avpl->len) { + + dbg_print (dbg_gog,2,dbg_facility,"reanalyze_gop: gog has new attributes let's look for new keys"); + + gog_keys = gog->cfg->keys; + + while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) { + gop_cfg = (mate_cfg_gop *)g_hash_table_lookup(mc->gopcfgs,curr_gogkey->name); + + if (( gogkey_match = new_avpl_pairs_match(gop_cfg->name, gog->avpl, curr_gogkey, TRUE, FALSE) )) { + + gog_key = (gogkey *)g_malloc(sizeof(gogkey)); + + gog_key->key = avpl_to_str(gogkey_match); + delete_avpl(gogkey_match,FALSE); + + gog_key->cfg = gop_cfg; + + if (g_hash_table_lookup(gop_cfg->gog_index,gog_key->key)) { + g_free(gog_key->key); + g_free(gog_key); + gog_key = NULL; + } + + if (! gog_key ) { + /* XXX: since these gogs actually share key info + we should try to merge (non released) gogs + that happen to have equal keys */ + } else { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: new key for gog=%s:%d : %s",gog->cfg->name,gog->id,gog_key->key); + g_ptr_array_add(gog->gog_keys,gog_key); + g_hash_table_insert(gog_key->cfg->gog_index,gog_key->key,gog); + } + + } + } + + gog->last_n = gog->avpl->len; + } + + if (gog->num_of_released_gops == gog->num_of_counting_gops) { + gog->released = TRUE; + gog->expiration = gog->cfg->expiration + rd->now; + } else { + gog->released = FALSE; + } +} + +static void analyze_gop(mate_config* mc, mate_gop* gop) { + mate_cfg_gog* cfg = NULL; + LoAL* gog_keys = NULL; + AVPL* curr_gogkey = NULL; + void* cookie = NULL; + AVPL* gogkey_match = NULL; + mate_gog* gog = NULL; + gchar* key = NULL; + + if ( ! gop->gog ) { + /* no gog, let's either find one or create it if due */ + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no gog"); + + gog_keys = (LoAL *)g_hash_table_lookup(mc->gogs_by_gopname,gop->cfg->name); + + if ( ! gog_keys ) { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no gog_keys for this gop"); + return; + } + + /* We have gog_keys! look for matching gogkeys */ + + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got gog_keys: %s",gog_keys->name) ; + + while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) { + if (( gogkey_match = new_avpl_pairs_match(gop->cfg->name, gop->avpl, curr_gogkey, TRUE, TRUE) )) { + + key = avpl_to_str(gogkey_match); + + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got gogkey_match: %s",key); + + if (( gog = (mate_gog *)g_hash_table_lookup(gop->cfg->gog_index,key) )) { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got already a matching gog"); + + if (gog->num_of_counting_gops == gog->num_of_released_gops && gog->expiration < rd->now) { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: this is a new gog, not the old one, let's create it"); + + gog_remove_keys(gog); + + new_gog(gog->cfg,gop); + + break; + } else { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: this is our gog"); + + if (! gop->gog ) adopt_gop(gog,gop); + + break; + } + } else { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no such gog in hash, let's create a new %s",curr_gogkey->name); + + cfg = (mate_cfg_gog *)g_hash_table_lookup(mc->gogcfgs,curr_gogkey->name); + + if (cfg) { + gog = new_gog(cfg,gop); + gog->num_of_gops = 1; + + if (gop->cfg->start) { + gog->num_of_counting_gops = 1; + } + + } else { + dbg_print (dbg_gog,0,dbg_facility,"analyze_gop: no such gog_cfg: %s",curr_gogkey->name); + } + + break; + } + + /** Can't get here because of "breaks" above */ + g_assert_not_reached(); + } + + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no gogkey_match: %s",key); + } /* while */ + + g_free(key); + key = NULL; + + if (gogkey_match) delete_avpl(gogkey_match,TRUE); + + reanalyze_gop(mc, gop); + } +} + + + +static void analyze_pdu(mate_config* mc, mate_pdu* pdu) { + /* TODO: + return a g_boolean to tell we've destroyed the pdu when the pdu is unnassigned + destroy the unassigned pdu + */ + mate_cfg_gop* cfg = NULL; + mate_gop* gop = NULL; + gchar* gop_key; + gchar* orig_gop_key = NULL; + AVPL* candidate_start = NULL; + AVPL* candidate_stop = NULL; + AVPL* is_start = NULL; + AVPL* is_stop = NULL; + AVPL* gopkey_match = NULL; + LoAL* gog_keys = NULL; + AVPL* curr_gogkey = NULL; + void* cookie = NULL; + AVPL* gogkey_match = NULL; + gchar* gogkey_str = NULL; + + dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: %s",pdu->cfg->name); + + if (! (cfg = (mate_cfg_gop *)g_hash_table_lookup(mc->gops_by_pduname,pdu->cfg->name)) ) + return; + + if ((gopkey_match = new_avpl_pairs_match("gop_key_match", pdu->avpl, cfg->key, TRUE, TRUE))) { + gop_key = avpl_to_str(gopkey_match); + + g_hash_table_lookup_extended(cfg->gop_index,(gconstpointer)gop_key,(gpointer *)&orig_gop_key,(gpointer *)&gop); + + if ( gop ) { + g_free(gop_key); + + /* is the gop dead ? */ + if ( ! gop->released && + ( ( gop->cfg->lifetime > 0.0 && gop->time_to_die >= rd->now) || + ( gop->cfg->idle_timeout > 0.0 && gop->time_to_timeout >= rd->now) ) ) { + dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: expiring released gop"); + gop->released = TRUE; + + if (gop->gog && gop->cfg->start) gop->gog->num_of_released_gops++; + } + + /* TODO: is the gop expired? */ + + gop_key = orig_gop_key; + + dbg_print (dbg_gop,2,dbg_facility,"analyze_pdu: got gop: %s",gop_key); + + if (( candidate_start = cfg->start )) { + + dbg_print (dbg_gop,2,dbg_facility,"analyze_pdu: got candidate start"); + + if (( is_start = new_avpl_pairs_match("", pdu->avpl, candidate_start, TRUE, FALSE) )) { + delete_avpl(is_start,FALSE); + if ( gop->released ) { + dbg_print (dbg_gop,3,dbg_facility,"analyze_pdu: start on released gop, let's create a new gop"); + + g_hash_table_remove(cfg->gop_index,gop_key); + gop->gop_key = NULL; + gop = new_gop(cfg,pdu,gop_key); + g_hash_table_insert(cfg->gop_index,gop_key,gop); + } else { + dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: duplicate start on gop"); + } + } + } + + pdu->gop = gop; + + if (gop->last_pdu) gop->last_pdu->next = pdu; + gop->last_pdu = pdu; + pdu->next = NULL; + pdu->time_in_gop = rd->now - gop->start_time; + + if (gop->released) pdu->after_release = TRUE; + + } else { + + dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: no gop already"); + + if ( ! cfg->start ) { + /* there is no GopStart, we'll check for matching GogKeys + if we have one we'll create the Gop */ + + apply_extras(pdu->avpl,gopkey_match,cfg->extra); + + gog_keys = (LoAL *)g_hash_table_lookup(mc->gogs_by_gopname,cfg->name); + + if (gog_keys) { + + while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) { + if (( gogkey_match = new_avpl_pairs_match(cfg->name, gopkey_match, curr_gogkey, TRUE, FALSE) )) { + gogkey_str = avpl_to_str(gogkey_match); + + if (g_hash_table_lookup(cfg->gog_index,gogkey_str)) { + gop = new_gop(cfg,pdu,gop_key); + g_hash_table_insert(cfg->gop_index,gop_key,gop); + delete_avpl(gogkey_match,FALSE); + g_free(gogkey_str); + break; + } else { + delete_avpl(gogkey_match,FALSE); + g_free(gogkey_str); + } + } + } + + if ( ! gop ) { + g_free(gop_key); + delete_avpl(gopkey_match,TRUE); + return; + } + + } else { + g_free(gop_key); + delete_avpl(gopkey_match,TRUE); + return; + } + + } else { + candidate_start = cfg->start; + + if (( is_start = new_avpl_pairs_match("", pdu->avpl, candidate_start, TRUE, FALSE) )) { + delete_avpl(is_start,FALSE); + gop = new_gop(cfg,pdu,gop_key); + } else { + g_free(gop_key); + return; + } + + pdu->gop = gop; + } + } + + if (gop->last_pdu) gop->last_pdu->next = pdu; + gop->last_pdu = pdu; + pdu->next = NULL; + + pdu->time_in_gop = rd->now - gop->start_time; + + gop->num_of_pdus++; + gop->time_to_timeout = cfg->idle_timeout > 0.0 ? cfg->idle_timeout + rd->now : (float) -1.0 ; + + dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: merge with key"); + + merge_avpl(gop->avpl,gopkey_match,TRUE); + delete_avpl(gopkey_match,TRUE); + + dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: apply extras"); + + apply_extras(pdu->avpl,gop->avpl,gop->cfg->extra); + + gop->last_time = pdu->rel_time; + + if ( ! gop->released) { + candidate_stop = cfg->stop; + + if (candidate_stop) { + is_stop = new_avpl_pairs_match("", pdu->avpl, candidate_stop, TRUE, FALSE); + } else { + is_stop = new_avpl(""); + } + + if(is_stop) { + dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: is a `stop"); + delete_avpl(is_stop,FALSE); + + if (! gop->released) { + gop->released = TRUE; + gop->release_time = pdu->rel_time; + if (gop->gog && gop->cfg->start) gop->gog->num_of_released_gops++; + } + + pdu->is_stop = TRUE; + + } + } + + if (gop->last_n != gop->avpl->len) apply_transforms(gop->cfg->transforms,gop->avpl); + + gop->last_n = gop->avpl->len; + + if (gop->gog) { + reanalyze_gop(mc, gop); + } else { + analyze_gop(mc, gop); + } + + } else { + dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: no match for this pdu"); + + pdu->gop = NULL; + } +} + +static void get_pdu_fields(gpointer k, gpointer v, gpointer p) { + int hfid = *((int*) k); + gchar* name = (gchar*) v; + tmp_pdu_data* data = (tmp_pdu_data*) p; + GPtrArray* fis; + field_info* fi; + guint i,j; + mate_range* curr_range; + guint start; + guint end; + AVP* avp; + gchar* s; + + + fis = proto_get_finfo_ptr_array(data->tree, hfid); + + if (fis) { + for (i = 0; i < fis->len; i++) { + fi = (field_info*) g_ptr_array_index(fis,i); + + + start = fi->start; + end = fi->start + fi->length; + + dbg_print(dbg_pdu,5,dbg_facility,"get_pdu_fields: found field %i-%i",start,end); + + for (j = 0; j < data->ranges->len; j++) { + + curr_range = (mate_range*) g_ptr_array_index(data->ranges,j); + + if (curr_range->end >= end && curr_range->start <= start) { + avp = new_avp_from_finfo(name, fi); + + if (*dbg_pdu > 4) { + s = avp_to_str(avp); + dbg_print(dbg_pdu,0,dbg_facility,"get_pdu_fields: got %s",s); + g_free(s); + } + + if (! insert_avp(data->pdu->avpl,avp) ) { + delete_avp(avp); + } + + } + } + } + } +} + +static mate_pdu* new_pdu(mate_cfg_pdu* cfg, guint32 framenum, field_info* proto, proto_tree* tree) { + mate_pdu* pdu = (mate_pdu*)g_slice_new(mate_max_size); + field_info* cfi; + GPtrArray* ptrs; + mate_range* range; + mate_range* proto_range; + tmp_pdu_data data; + guint i,j; + gint min_dist; + field_info* range_fi; + gint32 last_start; + gint32 first_end; + gint32 curr_end; + int hfid; + + dbg_print (dbg_pdu,1,dbg_facility,"new_pdu: type=%s framenum=%i",cfg->name,framenum); + + pdu->id = ++(cfg->last_id); + pdu->cfg = cfg; + + pdu->avpl = new_avpl(cfg->name); + + pdu->frame = framenum; + pdu->next_in_frame = NULL; + pdu->rel_time = rd->now; + + pdu->gop = NULL; + pdu->next = NULL; + pdu->time_in_gop = -1.0f; + + pdu->first = FALSE; + pdu->is_start = FALSE; + pdu->is_stop = FALSE; + pdu->after_release = FALSE; + + data.ranges = g_ptr_array_new(); + data.pdu = pdu; + data.tree = tree; + + /* first we create the proto range */ + proto_range = (mate_range *)g_malloc(sizeof(mate_range)); + proto_range->start = proto->start; + proto_range->end = proto->start + proto->length; + g_ptr_array_add(data.ranges,proto_range); + + dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: proto range %u-%u",proto_range->start,proto_range->end); + + last_start = proto_range->start; + + /* we move forward in the tranport */ + for (i = cfg->transport_ranges->len; i--; ) { + hfid = *((int*)g_ptr_array_index(cfg->transport_ranges,i)); + ptrs = proto_get_finfo_ptr_array(tree, hfid); + min_dist = 99999; + range_fi = NULL; + + if (ptrs) { + for (j=0; j < ptrs->len; j++) { + cfi = (field_info*) g_ptr_array_index(ptrs,j); + if (cfi->start < last_start && min_dist >= (last_start - cfi->start) ) { + range_fi = cfi; + min_dist = last_start - cfi->start; + } + } + + if ( range_fi ) { + range = (mate_range *)g_malloc(sizeof(*range)); + range->start = range_fi->start; + range->end = range_fi->start + range_fi->length; + g_ptr_array_add(data.ranges,range); + + last_start = range_fi->start; + + dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: transport(%i) range %i-%i",hfid,range->start,range->end); + } else { + /* we missed a range */ + dbg_print(dbg_pdu,6,dbg_facility,"new_pdu: transport(%i) missed",hfid); + } + + } + } + + if (cfg->payload_ranges) { + + first_end = proto_range->end; + + for (i = 0 ; i < cfg->payload_ranges->len; i++) { + hfid = *((int*)g_ptr_array_index(cfg->payload_ranges,i)); + ptrs = proto_get_finfo_ptr_array(tree, hfid); + min_dist = 99999; + range_fi = NULL; + + if (ptrs) { + for (j=0; j < ptrs->len; j++) { + cfi = (field_info*) g_ptr_array_index(ptrs,j); + curr_end = cfi->start + cfi->length; + if (curr_end > first_end && min_dist >= (curr_end - first_end) ) { + range_fi = cfi; + min_dist = curr_end - first_end; + } + } + + if ( range_fi ) { + range = (mate_range *)g_malloc(sizeof(*range)); + range->start = range_fi->start; + range->end = range_fi->start + range_fi->length; + g_ptr_array_add(data.ranges,range); + + dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: payload(%i) range %i-%i",hfid,range->start,range->end); + } else { + /* we missed a range */ + dbg_print(dbg_pdu,5,dbg_facility,"new_pdu: payload(%i) missed",hfid); + } + + } + } + } + + g_hash_table_foreach(cfg->hfids_attr,get_pdu_fields,&data); + + apply_transforms(pdu->cfg->transforms,pdu->avpl); + + g_ptr_array_foreach(data.ranges, (GFunc)g_free, NULL); + g_ptr_array_free(data.ranges,TRUE); + + return pdu; +} + + +extern void mate_analyze_frame(mate_config *mc, packet_info *pinfo, proto_tree* tree) { + mate_cfg_pdu* cfg; + GPtrArray* protos; + field_info* proto; + guint i,j; + AVPL* criterium_match; + + mate_pdu* pdu = NULL; + mate_pdu* last = NULL; + + rd->now = (float) nstime_to_sec(&pinfo->rel_ts); + + if ( proto_tracking_interesting_fields(tree) + && rd->highest_analyzed_frame < pinfo->num ) { + for ( i = 0; i < mc->pducfglist->len; i++ ) { + + cfg = (mate_cfg_pdu *)g_ptr_array_index(mc->pducfglist,i); + + dbg_print (dbg_pdu,4,dbg_facility,"mate_analyze_frame: trying to extract: %s",cfg->name); + protos = proto_get_finfo_ptr_array(tree, cfg->hfid_proto); + + if (protos) { + pdu = NULL; + + for (j = 0; j < protos->len; j++) { + + dbg_print (dbg_pdu,3,dbg_facility,"mate_analyze_frame: found matching proto, extracting: %s",cfg->name); + + proto = (field_info*) g_ptr_array_index(protos,j); + pdu = new_pdu(cfg, pinfo->num, proto, tree); + + if (cfg->criterium) { + criterium_match = new_avpl_from_match(cfg->criterium_match_mode,"",pdu->avpl,cfg->criterium,FALSE); + + if (criterium_match) { + delete_avpl(criterium_match,FALSE); + } + + if ( (criterium_match && cfg->criterium_accept_mode == REJECT_MODE ) + || ( ! criterium_match && cfg->criterium_accept_mode == ACCEPT_MODE )) { + + delete_avpl(pdu->avpl,TRUE); + g_slice_free(mate_max_size,(mate_max_size*)pdu); + pdu = NULL; + + continue; + } + } + + analyze_pdu(mc, pdu); + + if ( ! pdu->gop && cfg->drop_unassigned) { + delete_avpl(pdu->avpl,TRUE); + g_slice_free(mate_max_size,(mate_max_size*)pdu); + pdu = NULL; + continue; + } + + if ( cfg->discard ) { + delete_avpl(pdu->avpl,TRUE); + pdu->avpl = NULL; + } + + if (!last) { + g_hash_table_insert(rd->frames,GINT_TO_POINTER(pinfo->num),pdu); + last = pdu; + } else { + last->next_in_frame = pdu; + last = pdu; + } + + } + + if ( pdu && cfg->last_extracted ) break; + } + } + + rd->highest_analyzed_frame = pinfo->num; + } +} + +extern mate_pdu* mate_get_pdus(guint32 framenum) { + + if (rd) { + return (mate_pdu*) g_hash_table_lookup(rd->frames,GUINT_TO_POINTER(framenum)); + } else { + return NULL; + } +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + * + * vi: set shiftwidth=8 tabstop=8 noexpandtab: + * :indentSize=8:tabSize=8:noTabs=false: + */ |