Exemplo n.º 1
0
static int store_reply( struct cell *trans, int branch, struct sip_msg *rpl)
{
#		ifdef EXTRA_DEBUG
		if (trans->uac[branch].reply) {
			LM_ERR("replacing stored reply; aborting\n");
			abort();
		}
#		endif

		/* when we later do things such as challenge aggregation,
	   	   we should parse the message here before we conserve
		   it in shared memory; -jiri
		*/
		if (rpl==FAKED_REPLY)
			trans->uac[branch].reply=FAKED_REPLY;
		else
			trans->uac[branch].reply = sip_msg_cloner( rpl, 0 );

		if (! trans->uac[branch].reply ) {
			LM_ERR("failed to alloc' clone memory\n");
			return 0;
		}

		return 1;
}
Exemplo n.º 2
0
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
				transaction_cb cb, void* cbp,release_tmcb_param release_func)
{
	union sockaddr_union to_su, new_to_su;
	struct cell *new_cell;
	struct cell *backup_cell;
	struct retr_buf *request;
	static struct sip_msg *req;
	struct usr_avp **backup;
	char *buf, *buf1;
	int buf_len, buf_len1;
	int ret, flags, sflag_bk;
	int backup_route_type;
	int sip_msg_len;
	unsigned int hi;
	struct socket_info *new_send_sock;
	str h_to, h_from, h_cseq, h_callid;
	struct proxy_l *proxy, *new_proxy;
	unsigned short dst_changed;

	ret=-1;

	/*** added by dcm
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error3;

	if(dialog->obp.s)
		dialog->hooks.next_hop = &dialog->obp;

	LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);

	/* calculate the socket corresponding to next hop */
	proxy = uri2proxy( dialog->hooks.next_hop,
		dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE );
	if (proxy==0)  {
		ret=E_BAD_ADDRESS;
		goto error3;
	}
	/* use the first address */
	hostent2su( &to_su,
		&proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT);

	/* check/discover the send socket */
	if (dialog->send_sock) {
		/* if already set, the protocol of send sock must have the 
		   the same type as the proto required by destination URI */
		if (proxy->proto != dialog->send_sock->proto)
			dialog->send_sock = NULL;
	}
	if (dialog->send_sock==NULL) {
		/* get the send socket */
		dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto);
		if (!dialog->send_sock) {
			LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family);
			ser_error = E_NO_SOCKET;
			goto error2;
		}
	}
	LM_DBG("sending socket is %.*s \n",
		dialog->send_sock->name.len,dialog->send_sock->name.s);


	/* ***** Create TRANSACTION and all related  ***** */
	new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/);
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LM_ERR("short of cell shmem\n");
		goto error2;
	}

	/* pass the transaction flags from dialog to transaction */
	new_cell->flags |= dialog->T_flags;

	/* add the callback the transaction for LOCAL_COMPLETED event */
	flags = TMCB_LOCAL_COMPLETED;
	/* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */
	if (pass_provisional_replies || pass_provisional(new_cell))
		flags |= TMCB_LOCAL_RESPONSE_OUT;
	if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){
		ret=E_OUT_OF_MEM;
		LM_ERR("short of tmcb shmem\n");
		goto error2;
	}

	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)
		new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->flags |= T_IS_LOCAL_FLAG;

	request = &new_cell->uac[0].request;
	if (dialog->forced_to_su.s.sa_family == AF_UNSPEC)
		request->dst.to = to_su;
	else
		request->dst.to = dialog->forced_to_su;
	request->dst.send_sock = dialog->send_sock;
	request->dst.proto = dialog->send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	/* copy AVPs into transaction */
	new_cell->user_avps = dialog->avps;
	dialog->avps = NULL;


	/* ***** Create the message buffer ***** */
	buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len);
	if (!buf) {
		LM_ERR("failed to build message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	if (local_rlist.a) {
		LM_DBG("building sip_msg from buffer\n");
		req = buf_to_sip_msg(buf, buf_len, dialog);
		if (req==NULL) {
			LM_ERR("failed to build sip_msg from buffer\n");
		} else {
			/* set this transaction as active one */
			backup_cell = get_t();
			set_t( new_cell );
			/* set transaction AVP list */
			backup = set_avp_list( &new_cell->user_avps );
			/* backup script flags */
			sflag_bk = getsflags();
			/* disable parallel forking */
			set_dset_state( 0 /*disable*/);

			/* run the route */
			swap_route_type( backup_route_type, LOCAL_ROUTE);
			run_top_route( local_rlist.a, req);
			set_route_type( backup_route_type );

			/* transfer current message context back to t */
			new_cell->uac[0].br_flags = getb0flags(req);
			/* restore the prevoius active transaction */
			set_t( backup_cell );

			set_dset_state( 1 /*enable*/);
			setsflagsval(sflag_bk);
			set_avp_list( backup );

			/* check for changes - if none, do not regenerate the buffer */
			dst_changed = 1;
			if (req->new_uri.s || req->force_send_socket!=dialog->send_sock ||
			req->dst_uri.len != dialog->hooks.next_hop->len ||
			memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) ||
			(dst_changed=0)==0 || req->add_rm || req->body_lumps){

				new_send_sock = NULL;
				/* do we also need to change the destination? */
				if (dst_changed) {
					/* calculate the socket corresponding to next hop */
					new_proxy = uri2proxy(
						req->dst_uri.s ? &(req->dst_uri) : &req->new_uri,
						PROTO_NONE );
					if (new_proxy==0)
						goto abort_update;
					/* use the first address */
					hostent2su( &new_to_su,
						&new_proxy->host, new_proxy->addr_idx,
						new_proxy->port ? new_proxy->port:SIP_PORT);
					/* get the send socket */
					new_send_sock = get_send_socket( req, &new_to_su,
						new_proxy->proto);
					if (!new_send_sock) {
						free_proxy( new_proxy );
						pkg_free( new_proxy );
						LM_ERR("no socket found for the new destination\n");
						goto abort_update;
					}
				}

				/* if interface change, we need to re-build the via */
				if (new_send_sock && new_send_sock != dialog->send_sock) {
					LM_DBG("Interface change in local route -> "
						"rebuilding via\n");
					if (!del_lump(req,req->h_via1->name.s - req->buf,
					req->h_via1->len,0)) {
						LM_ERR("Failed to remove initial via \n");
						goto abort_update;
					}

					memcpy(req->add_to_branch_s,req->via1->branch->value.s,
						req->via1->branch->value.len);
					req->add_to_branch_len = req->via1->branch->value.len;

					/* update also info about new destination and send sock */
					dialog->send_sock = new_send_sock;
					free_proxy( proxy );
					pkg_free( proxy );
					proxy = new_proxy;
					request->dst.send_sock = new_send_sock;
					request->dst.proto = new_send_sock->proto;
					request->dst.proto_reserved1 = 0;

					/* build the shm buffer now */
					set_init_lump_flags(LUMPFLAG_BRANCH);
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						new_send_sock, new_send_sock->proto,
						MSG_TRANS_SHM_FLAG);
					reset_init_lump_flags();
					del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH);

				} else {

					LM_DBG("Change in local route -> rebuilding buffer\n");
					/* build the shm buffer now */
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						dialog->send_sock, dialog->send_sock->proto,
						MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG);
					/* now as it used, hide the original VIA header */
					del_lump(req,req->h_via1->name.s - req->buf,
						req->h_via1->len, 0);

				}

				if (!buf1) {
					LM_ERR("no more shm mem\n");
					/* keep original buffer */
					goto abort_update;
				}
				/* update shortcuts */
				if(!req->add_rm && !req->new_uri.s) {
					/* headers are not affected, simply tranlate */
					new_cell->from.s = new_cell->from.s - buf + buf1;
					new_cell->to.s = new_cell->to.s - buf + buf1;
					new_cell->callid.s = new_cell->callid.s - buf + buf1;
					new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1;
				} else {
					/* use heavy artilery :D */
					if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to,
					&h_cseq, &h_callid)!=0 ) {
						LM_ERR("failed to update shortcut pointers\n");
						shm_free(buf1);
						goto abort_update;
					}
					new_cell->from = h_from;
					new_cell->to = h_to;
					new_cell->callid = h_callid;
					new_cell->cseq_n = h_cseq;
				}
				/* here we rely on how build_uac_req()
				   builds the first line */
				new_cell->uac[0].uri.s = buf1 +
					req->first_line.u.request.method.len + 1;
				new_cell->uac[0].uri.len = GET_RURI(req)->len;

				/* update also info about new destination and send sock */
				if (new_send_sock)
					request->dst.to = new_to_su;

				shm_free(buf);
				buf = buf1;
				buf_len = buf_len1;
				/* use new buffer */
			} else {
				/* no changes over the message, buffer is already generated,
				   just hide the original VIA for potential further branches */
				del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0);
			}
abort_update:
			/* save the SIP message into transaction */
			new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1);
			if (new_cell->uas.request==NULL) {
				/* reset any T triggering */
				new_cell->on_negative = 0;
				new_cell->on_reply = 0;
			} else {
				new_cell->uas.end_request=
					((char*)new_cell->uas.request)+sip_msg_len;
			}
			/* no parallel support in UAC transactions */
			new_cell->on_branch = 0;
			free_sip_msg(req);
		}
	}

	/* for DNS based failover, copy the DNS proxy into transaction */
	if (!disable_dns_failover) {
		new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/);
		if (new_cell->uac[0].proxy==NULL)
			LM_ERR("failed to store DNS info -> no DNS based failover\n");
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer.s = buf;
	request->buffer.len = buf_len;
	new_cell->nr_of_outgoings++;

	if(last_localT) {
		*last_localT = new_cell;
		REF_UNSAFE(new_cell);
	}

	if (SEND_BUFFER(request) == -1) {
		LM_ERR("attempt to send to '%.*s' failed\n",
			dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	}

	if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) {
		t_release_transaction(new_cell);
	} else {
		start_retr(request);
	}

	free_proxy( proxy );
	pkg_free( proxy );

	return 1;

error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);
error2:
	free_proxy( proxy );
	pkg_free( proxy );
error3:
	return ret;
}
Exemplo n.º 3
0
/* Suspends the transaction for later use.
 * Save the returned hash_index and label to get
 * back to the SIP request processing, see the readme.
 *
 * Return value:
 * 	0  - success
 * 	<0 - failure
 */
int t_suspend(struct sip_msg *msg,
		unsigned int *hash_index, unsigned int *label)
{
	struct cell	*t;
	int branch;
	int sip_msg_len;

	t = get_t();
	if (!t || t == T_UNDEFINED) {
		LM_ERR("transaction has not been created yet\n");
		return -1;
	}

	if (t->flags & T_CANCELED) {
		/* The transaction has already been canceled */
		LM_DBG("trying to suspend an already canceled transaction\n");
		ser_error = E_CANCELED;
		return 1;
	}
	if (t->uas.status >= 200) {
		LM_DBG("trasaction sent out a final response already - %d\n",
				t->uas.status);
		return -3;
	}

	if (msg->first_line.type != SIP_REPLY) {
		/* send a 100 Trying reply, because the INVITE processing
		will probably take a long time */
		if (msg->REQ_METHOD==METHOD_INVITE && (t->flags&T_AUTO_INV_100)
			&& (t->uas.status < 100)
		) {
			if (!t_reply( t, msg , 100 ,
				cfg_get(tm, tm_cfg, tm_auto_inv_100_r)))
				LM_DBG("suspending request processing - sending 100 reply\n");
		}

		if ((t->nr_of_outgoings==0) && /* if there had already been
			an UAC created, then the lumps were
			saved as well */
			save_msg_lumps(t->uas.request, msg)
		) {
			LM_ERR("failed to save the message lumps\n");
			return -1;
		}
		/* save the message flags */
		t->uas.request->flags = msg->flags;

		/* add a blind UAC to let the fr timer running */
		if (add_blind_uac() < 0) {
			LM_ERR("failed to add the blind UAC\n");
			return -1;
		}
		/* propagate failure route to new branch
		 * - failure route to be executed if the branch is not continued
		 *   before timeout */
		t->uac[t->async_backup.blind_uac].on_failure = t->on_failure;
		t->flags |= T_ASYNC_SUSPENDED;
	} else {
		LM_DBG("this is a suspend on reply - setting msg flag to SUSPEND\n");
		msg->msg_flags |= FL_RPL_SUSPENDED;
		/* this is a reply suspend find which branch */

		if (t_check( msg  , &branch )==-1){
			LOG(L_ERR, "ERROR: t_suspend_reply: " \
				"failed find UAC branch\n");
			return -1; 
		}
		LM_DBG("found a a match with branch id [%d] - "
				"cloning reply message to t->uac[branch].reply\n", branch);

		sip_msg_len = 0;
		t->uac[branch].reply = sip_msg_cloner( msg, &sip_msg_len );

		if (! t->uac[branch].reply ) {
			LOG(L_ERR, "can't alloc' clone memory\n");
			return -1;
		}
		t->uac[branch].end_reply = ((char*)t->uac[branch].reply) + sip_msg_len;

		LM_DBG("saving transaction data\n");
		t->uac[branch].reply->flags = msg->flags;
		t->flags |= T_ASYNC_SUSPENDED;
	}

	*hash_index = t->hash_index;
	*label = t->label;



	/* backup some extra info that can be used in continuation logic */
	t->async_backup.backup_route = get_route_type();
	t->async_backup.backup_branch = get_t_branch();
	t->async_backup.ruri_new = ruri_get_forking_state();


	return 0;
}
Exemplo n.º 4
0
struct cell*  build_cell( struct sip_msg* p_msg )
{
	struct cell* new_cell;
	unsigned int i;
	unsigned int myrand;
	int size;
	char *c;
	struct ua_client *uac;

	/* avoid 'unitialized var use' warning */
	myrand=0;

	/* allocs a new cell */
	new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) );
	if  ( !new_cell ) {
		ser_error=E_OUT_OF_MEM;
		return NULL;
	}

	/* filling with 0 */
	memset( new_cell, 0, sizeof( struct cell ) );

	/* UAS */
#ifdef EXTRA_DEBUG
	new_cell->uas.response.retr_timer.tg=TG_RT;
	new_cell->uas.response.fr_timer.tg=TG_FR;
#endif
	new_cell->uas.response.fr_timer.payload =
	new_cell->uas.response.retr_timer.payload = &(new_cell->uas.response);
	new_cell->uas.response.my_T=new_cell;

	/* bogdan - debug */
	/*fprintf(stderr,"before clone VIA |%.*s|\n",via_len(p_msg->via1),
		via_s(p_msg->via1,p_msg));*/

	/* enter callback, which may potentially want to parse some stuff,
	   before the request is shmem-ized
	*/ 
    if (p_msg) callback_event(TMCB_REQUEST_IN, new_cell, p_msg,
            p_msg->REQ_METHOD );

	if (p_msg) {
		new_cell->uas.request = sip_msg_cloner(p_msg);
		if (!new_cell->uas.request)
			goto error;
	}

	/* new_cell->uas.to_tag = &( get_to(new_cell->uas.request)->tag_value ); */
	new_cell->uas.response.my_T = new_cell;

	/* UAC */
	for(i=0;i<MAX_BRANCHES;i++)
	{
		uac=&new_cell->uac[i];
		uac->request.my_T = new_cell;
		uac->request.branch = i;
#ifdef EXTRA_DEBUG
		uac->request.fr_timer.tg = TG_FR;
		uac->request.retr_timer.tg = TG_RT;
#endif
		uac->request.retr_timer.payload = 
		uac->request.fr_timer.payload = &uac->request;
		uac->local_cancel=uac->request;
	}

	/* global data for transaction */
	if (p_msg) {
		new_cell->hash_index = p_msg->hash_index;
	} else {
		/* note: unsatisfactory if 
		   RAND_MAX < TABLE_ENTRIES
		*/
		myrand = rand();
		new_cell->hash_index = myrand % TABLE_ENTRIES ;
	}
	new_cell->wait_tl.payload = new_cell;
	new_cell->dele_tl.payload = new_cell;
	new_cell->relaied_reply_branch   = -1;
	/* new_cell->T_canceled = T_UNDEFINED; */
#ifdef EXTRA_DEBUG
	new_cell->wait_tl.tg=TG_WT;
	new_cell->dele_tl.tg=TG_DEL;
#endif

	if (!syn_branch) {
		if (p_msg) {
			/* char value of a proxied transaction is
			   calculated out of header-fileds forming
			   transaction key
			*/
			char_msg_val( p_msg, new_cell->md5 );
		} else {
			/* char value for a UAC transaction is created
			   randomly -- UAC is an originating stateful element 
			   which cannot be refreshed, so the value can be
			   anything
			*/
			/* HACK : not long enough */
			c=new_cell->md5;
			size=MD5_LEN;
			memset(c, '0', size );
			int2reverse_hex( &c, &size, myrand );
		}
	}

	init_cell_lock(  new_cell );
	return new_cell;

error:
	shm_free(new_cell);
	return NULL;
}
Exemplo n.º 5
0
static inline int do_dns_failover(struct cell *t)
{
	static struct sip_msg faked_req;
	struct sip_msg *shmem_msg;
	struct sip_msg *req;
	struct ua_client *uac;
	dlg_t dialog;
	int ret, sip_msg_len;

	uac = &t->uac[picked_branch];

	/* check if the DNS resolver can get at least one new IP */
	if ( get_next_su( uac->proxy, &uac->request.dst.to, 1)!=0 )
		return -1;

	LM_DBG("new destination available\n");

	if (t->uas.request==NULL) {
		if (!is_local(t)) {
			LM_CRIT("BUG: proxy transaction without UAS request :-/\n");
			return -1;
		}
		/* create the cloned SIP msg -> first create a new SIP msg */
		memset( &dialog, 0, sizeof(dialog));
		dialog.send_sock = uac->request.dst.send_sock;
		dialog.hooks.next_hop = &uac->uri;
		req = buf_to_sip_msg(uac->request.buffer.s, uac->request.buffer.len,
			&dialog);
		if (req==NULL) {
			LM_ERR("failed to generate SIP msg from previous buffer\n");
			return -1;
		}
		/* now do the actual cloning of the SIP message */
		t->uas.request = sip_msg_cloner( req, &sip_msg_len, 1);
		if (t->uas.request==NULL) {
			LM_ERR("cloning failed\n");
			free_sip_msg(req);
			return -1;
		}
		t->uas.end_request = ((char*)t->uas.request) + sip_msg_len;
		/* free the actual SIP message, keep the clone only */
		free_sip_msg(req);
		/* the sip_msg structure is static in buf_to_sip_msg,
		   so no need to free it */
	}
	shmem_msg = t->uas.request;

	if (!fake_req(&faked_req, shmem_msg, &t->uas, uac, 1/*with dst_uri*/)) {
		LM_ERR("fake_req failed\n");
		return -1;
	}
	/* fake also the env. conforming to the fake msg */
	faked_env( t, &faked_req);
	ret = -1;

	/* set info as current destination */
	if ( set_ruri( &faked_req, &uac->uri)!= 0)
		goto done;

	setb0flags( &faked_req, uac->br_flags );
	faked_req.force_send_socket = shmem_msg->force_send_socket;

	/* send it out */
	if (t_forward_nonack( t, &faked_req, uac->proxy)==1)
		ret = 0;

done:
	/* restore original environment and free the fake msg */
	faked_env( t, 0);
	free_faked_req(&faked_req,t);
	return ret;
}
Exemplo n.º 6
0
struct cell*  build_cell( struct sip_msg* p_msg )
{
	struct cell* new_cell;
	int          sip_msg_len;
	avp_list_t* old;

	/* allocs a new cell */
	new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) );
	if  ( !new_cell ) {
		ser_error=E_OUT_OF_MEM;
		return NULL;
	}

	/* filling with 0 */
	memset( new_cell, 0, sizeof( struct cell ) );

	/* UAS */
	new_cell->uas.response.my_T=new_cell;
	init_rb_timers(&new_cell->uas.response);
	/* timers */
	init_cell_timers(new_cell);

	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI,  &new_cell->uri_avps_from );
	new_cell->uri_avps_from = *old;
	*old = 0;

	old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI,  &new_cell->uri_avps_to );
	new_cell->uri_avps_to = *old;
	*old = 0;

	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER,  &new_cell->user_avps_from );
	new_cell->user_avps_from = *old;
	*old = 0;

	old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER,  &new_cell->user_avps_to );
	new_cell->user_avps_to = *old;
	*old = 0;

	     /* We can just store pointer to domain avps in the transaction context,
	      * because they are read-only
	      */
	new_cell->domain_avps_from = get_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN);
	new_cell->domain_avps_to = get_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN);

	/* enter callback, which may potentially want to parse some stuff,
	 * before the request is shmem-ized */
	if ( p_msg && has_reqin_tmcbs() )
		run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);

	if (p_msg) {
		/* clean possible previous added vias/clen header or else they would 
		 * get propagated in the failure routes */
		free_via_clen_lump(&p_msg->add_rm);
		new_cell->uas.request = sip_msg_cloner(p_msg,&sip_msg_len);
		if (!new_cell->uas.request)
			goto error;
		new_cell->uas.end_request=((char*)new_cell->uas.request)+sip_msg_len;
	}

	/* UAC */
	init_branches(new_cell);

	new_cell->relayed_reply_branch   = -1;
	/* new_cell->T_canceled = T_UNDEFINED; */

	init_synonym_id(new_cell);
	init_cell_lock(  new_cell );
	return new_cell;

error:
	destroy_avp_list(&new_cell->user_avps_from);
	destroy_avp_list(&new_cell->user_avps_to);
	destroy_avp_list(&new_cell->uri_avps_from);
	destroy_avp_list(&new_cell->uri_avps_to);
	shm_free(new_cell);
	/* unlink transaction AVP list and link back the global AVP list (bogdan)*/
	reset_avps();
	return NULL;
}