Ejemplo n.º 1
0
/**
 * 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;
			}
		}
	}
}
Ejemplo n.º 2
0
/* 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);
	}
}
Ejemplo n.º 3
0
/**
 * 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);
	}

}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
/**
 * 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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
/**
 * 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;
}
Ejemplo n.º 8
0
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;
	}
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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;
	}
}
Ejemplo n.º 11
0
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);
	}
}
Ejemplo n.º 12
0
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;
	}
}
Ejemplo n.º 13
0
/**
 * 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;
}
Ejemplo n.º 14
0
/**
* 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;
	}
}