/** * avpl_transform: * @param src the source avpl for the transform operation. * @param op a pointer to the avpl transformation object to apply. * * Applies the "op" transformation to an avpl, matches it and eventually * replaces or inserts the transformed avps. * * Return value: whether the transformation was performed or not. **/ extern void avpl_transform(AVPL* src, AVPL_Transf* op) { AVPL* avpl = NULL; AVPN* cs; AVPN* cm; AVPN* n; #ifdef _AVP_DEBUGGING dbg_print(dbg_avpl_op,3,dbg_fp,"avpl_transform: src=%X op=%X",src,op); #endif for ( ; op ; op = op->next) { avpl = new_avpl_from_match(op->match_mode, src->name,src, op->match, TRUE); if (avpl) { switch (op->replace_mode) { case AVPL_NO_REPLACE: delete_avpl(avpl,TRUE); return; case AVPL_INSERT: merge_avpl(src,op->replace,TRUE); delete_avpl(avpl,TRUE); return; case AVPL_REPLACE: cs = src->null.next; cm = avpl->null.next; while(cs->avp) { if (cm->avp && cs->avp->n == cm->avp->n && cs->avp->v == cm->avp->v) { n = cs->next; cs->prev->next = cs->next; cs->next->prev = cs->prev; g_slice_free(any_avp_type,(any_avp_type*)cs); cs = n; cm = cm->next; } else { cs = cs->next; } } merge_avpl(src,op->replace,TRUE); delete_avpl(avpl,TRUE); return; } } } }
/* 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); } }
/** * delete_avpl_transform: * @param op a pointer to the avpl transformation object * * Destroys an avpl transformation object and releases all the resources it * uses. * **/ extern void delete_avpl_transform(AVPL_Transf* op) { AVPL_Transf* next; for (; op ; op = next) { next = op->next; g_free(op->name); if (op->match) { delete_avpl(op->match,TRUE); } if (op->replace) { delete_avpl(op->replace,TRUE); } g_free(op); } }
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; }
/** * delete_loal: * @param loal the loal to be deleted. * @param avpls_too whether avpls contained by the loal should be deleted as well * @param avps_too whether avps contained by the avpls should be also deleted * * Destroys a loal and eventually desstroys avpls and avps. * **/ extern void delete_loal(LoAL* loal, gboolean avpls_too, gboolean avps_too) { AVPL* avpl; #ifdef _AVP_DEBUGGING dbg_print(dbg_avpl_op,3,dbg_fp,"delete_loal: %X",loal); #endif while(( avpl = extract_last_avpl(loal) )) { if (avpls_too) { delete_avpl(avpl,avps_too); } } scs_unsubscribe(avp_strings,loal->name); g_slice_free(any_avp_type,(any_avp_type*)loal); }
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; }
/** * load_loal_error: * Used by loal_from_file to handle errors while loading. **/ static LoAL* load_loal_error(FILE* fp, LoAL* loal, AVPL* curr, int linenum, const gchar* fmt, ...) { va_list list; gchar* desc; LoAL* ret = NULL; gchar* err; va_start( list, fmt ); desc = g_strdup_vprintf(fmt, list); va_end( list ); err = g_strdup_printf("Error Loading LoAL from file: in %s at line: %i, %s",loal->name,linenum,desc); ret = new_loal(err); g_free(desc); g_free(err); if (fp) fclose(fp); if (loal) delete_loal(loal,TRUE,TRUE); if (curr) delete_avpl(curr,TRUE); return ret; }
extern void mate_analyze_frame(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->fd->rel_ts); if ( proto_tracking_interesting_fields(tree) && rd->highest_analyzed_frame < pinfo->fd->num ) { for ( i = 0; i < mc->pducfglist->len; i++ ) { cfg = 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->fd->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(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->fd->num),pdu); last = pdu; } else { last->next_in_frame = pdu; last = pdu; } } if ( pdu && cfg->last_extracted ) break; } } rd->highest_analyzed_frame = pinfo->fd->num; } }
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 void analyze_pdu(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 = g_hash_table_lookup(mc->gops_by_pduname,pdu->cfg->name)) ) return; if ((gopkey_match = new_avpl_exact_match("gop_key_match",pdu->avpl,cfg->key, 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_exact_match("",pdu->avpl, candidate_start, 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 = 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_exact_match(cfg->name,gopkey_match,curr_gogkey,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_exact_match("",pdu->avpl, candidate_start, 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_exact_match("",pdu->avpl, candidate_stop,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(gop); } else { analyze_gop(gop); } } else { dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: no match for this pdu"); pdu->gop = NULL; } }
static void analyze_gop(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 = 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_exact_match(gop->cfg->name,gop->avpl,curr_gogkey,TRUE) )) { key = avpl_to_str(gogkey_match); dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got gogkey_match: %s",key); if (( 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 = 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(gop); } }
static void reanalyze_gop(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 = g_hash_table_lookup(mc->gopcfgs,curr_gogkey->name); if (( gogkey_match = new_avpl_exact_match(gop_cfg->name,gog->avpl,curr_gogkey,FALSE) )) { gog_key = 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; } }
/** * new_avpl_exact_match: * @param name the name of the resulting avpl * @param src avpl to be matched agains an "op" avpl * @param op the "op" avpl that will be matched against the src avpl * @param copy_avps whether the avps in the resulting avpl should be copied * * creates an avp list containing every avp in src matching every avp in op * it will not create a list unless every avp in op is matched only once * to every avp in op. * * Return value: a pointer to the newly created avpl containing the * matching avps. **/ extern AVPL* new_avpl_exact_match(const gchar* name,AVPL* src, AVPL* op, gboolean copy_avps) { AVPL* newavpl = new_avpl(name); AVPN* co = NULL; AVPN* cs = NULL; ptrdiff_t c; AVP* m; AVP* copy; #ifdef _AVP_DEBUGGING dbg_print(dbg_avpl_op,3,dbg_fp,"new_avpl_every_match: %X src=%X op=%X name='%s'",newavpl,src,op,name); #endif if (op->len == 0) return newavpl; if (src->len == 0) { delete_avpl(newavpl,FALSE); return NULL; } cs = src->null.next; co = op->null.next; while(1) { c = ADDRDIFF(co->avp->n,cs->avp->n); if ( c > 0 ) { delete_avpl(newavpl,TRUE); return NULL; } else if (c < 0) { cs = cs->next; if (! cs->avp ) { delete_avpl(newavpl,TRUE); return NULL; } } else { m = match_avp(cs->avp,co->avp); if(m) { cs = cs->next; co = co->next; if (copy_avps) { copy = avp_copy(m); if ( ! insert_avp(newavpl,copy) ) { delete_avp(copy); } } else { insert_avp(newavpl,m); } if (!co->avp) { return newavpl; } if (!cs->avp) { delete_avpl(newavpl,TRUE); return NULL; } } else { delete_avpl(newavpl,TRUE); return NULL; } } } /* should never be reached */ return NULL; }
/** * new_avpl_every_match: * @param name the name of the resulting avpl * @param src avpl to be matched agains an "op" avpl * @param op the "op" avpl that will be matched against the src avpl * @param copy_avps whether the avps in the resulting avpl should be copied * * creates an avp list containing any avps in src matching every avp in op * it will not create a list if there is not a match for every attribute in op * * Return value: a pointer to the newly created avpl containing the * matching avps. **/ extern AVPL* new_avpl_every_match(const gchar* name, AVPL* src, AVPL* op, gboolean copy_avps) { AVPL* newavpl; AVPN* co = NULL; AVPN* cs = NULL; ptrdiff_t c; AVP* m; AVP* copy; gboolean matches; #ifdef _AVP_DEBUGGING dbg_print(dbg_avpl_op,3,dbg_fp,"new_avpl_every_match: %X src=%X op=%X name='%s'",newavpl,src,op,name); #endif if (src->len == 0) return NULL; newavpl = new_avpl(scs_subscribe(avp_strings, name)); if (op->len == 0) return newavpl; matches = TRUE; cs = src->null.next; co = op->null.next; while(1) { if (!co->avp) { break; } if (!cs->avp) { break; } c = ADDRDIFF(co->avp->n,cs->avp->n); if ( c > 0 ) { delete_avpl(newavpl,TRUE); return NULL; } else if (c < 0) { cs = cs->next; if (! cs->avp ) { break; } } else { m = match_avp(cs->avp,co->avp); if(m) { matches++; cs = cs->next; co = co->next; if (copy_avps) { copy = avp_copy(m); if ( ! insert_avp(newavpl,copy) ) { delete_avp(copy); } } else { insert_avp(newavpl,m); } } else { cs = cs->next; } } } if (matches) { return newavpl; } else { delete_avpl(newavpl,TRUE); return NULL; } }