Ejemplo n.º 1
0
/* run reply route functions */
int run_reply_route(struct sip_msg *_rpl, struct cell *_t, int index)
{
	avp_list_t	*backup_uri_from, *backup_uri_to;
	avp_list_t	*backup_user_from, *backup_user_to;
	avp_list_t	*backup_domain_from, *backup_domain_to;
	struct run_act_ctx	ra_ctx;

	if (!_t || (index < 0)) return -1;

	/* set the avp_list the one from transaction */
	backup_uri_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &_t->uri_avps_from );
	backup_uri_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &_t->uri_avps_to );
	backup_user_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &_t->user_avps_from );
	backup_user_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &_t->user_avps_to );
	backup_domain_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &_t->domain_avps_from );
	backup_domain_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &_t->domain_avps_to );

	init_run_actions_ctx(&ra_ctx);
	if (run_actions(&ra_ctx, onreply_rt.rlist[index], _rpl)<0)
		LOG(L_ERR, "ERROR: run_reply_route(): on_reply processing failed\n");

	/* restore original avp list */
	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_URI, backup_uri_from );
	set_avp_list( AVP_TRACK_TO | AVP_CLASS_URI, backup_uri_to );
	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_USER, backup_user_from );
	set_avp_list( AVP_TRACK_TO | AVP_CLASS_USER, backup_user_to );
	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_DOMAIN, backup_domain_from );
	set_avp_list( AVP_TRACK_TO | AVP_CLASS_DOMAIN, backup_domain_to );

	return 0;
}
Ejemplo n.º 2
0
static int dbops_foreach_func(struct sip_msg* m, char* handle, char* route_no) {
	int res;
	db_rec_t* rec;
	struct dbops_handle *a = (void *) handle;
	struct run_act_ctx ra_ctx;
	
	if ((long)route_no >= main_rt.idx) {
		BUG("invalid routing table number #%ld of %d\n", (long) route_no, main_rt.idx);
		return -1;
	}
	if (!main_rt.rlist[(long) route_no]) {
		WARN(MODULE_NAME": route not declared (hash:%ld)\n", (long) route_no);
		return -1;
	}
	res = check_query_opened(a, "for_each");
	if (res < 0) return res;

	res = -1;
	a->cur_row_no = 0;
	for(rec = db_first(a->result);
			rec != NULL;
			rec = db_next(a->result),
			a->cur_row_no++) {
		/* exec the routing script */
		init_run_actions_ctx(&ra_ctx);
		res = run_actions(&ra_ctx, main_rt.rlist[(long) route_no], m);
		if (res <= 0) break;
	}
	if (!rec) a->cur_row_no = -1;
	return res;
}
Ejemplo n.º 3
0
int run_top_route(struct action* a, struct sip_msg* msg)
{
	static unsigned int bl_last_msg_id = 0;
	int bk_action_flags;
	int bk_rec_lev;
	int ret;

	bk_action_flags = action_flags;
	bk_rec_lev = rec_lev;

	action_flags = 0;
	rec_lev = 0;
	init_err_info();

	if (bl_last_msg_id != msg->id) {
		bl_last_msg_id = msg->id;
		reset_bl_markers();
	}

	resetsflag( (unsigned int)-1 );

	run_actions(a, msg);
	ret = action_flags;

	action_flags = bk_action_flags;
	rec_lev = bk_rec_lev;
	/* reset script tracing */
	use_script_trace = 0;

	return ret;
}
Ejemplo n.º 4
0
Archivo: action.c Proyecto: ryzhov/ATS0
/* run a list of actions */
int run_action_list(struct action* a, struct sip_msg* msg)
{
	int ret=E_UNSPEC;
	struct action* t;
	for (t=a; t!=0; t=t->next){
		ret=do_action(t, msg);
		/* if action returns 0, then stop processing the script */
		if(ret==0)
			action_flags |= ACT_FL_EXIT;
		if(error_rlist.a!=NULL &&
				(route_type&(ERROR_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE))==0
				&& _oser_err_info.eclass!=0)

		{
			LM_DBG("jumping to error route\n");
			set_route_type( ERROR_ROUTE );
			run_actions(error_rlist.a, msg);
			/* if don't exit, then reset error info */
			if(!(action_flags&ACT_FL_EXIT))
				init_err_info();
		}
		
		if((action_flags&ACT_FL_RETURN) || (action_flags&ACT_FL_EXIT))
			break;
	}
	return ret;
}
Ejemplo n.º 5
0
static int xhttp_process_request(sip_msg_t* orig_msg, 
							  char* new_buf, unsigned int new_len)
{
	int ret;
	sip_msg_t tmp_msg, *msg;
	struct run_act_ctx ra_ctx;
	
	ret=0;
	if (new_buf && new_len)
	{
		memset(&tmp_msg, 0, sizeof(sip_msg_t));
		tmp_msg.buf = new_buf;
		tmp_msg.len = new_len;
		tmp_msg.rcv = orig_msg->rcv;
		tmp_msg.id = orig_msg->id;
		tmp_msg.set_global_address = orig_msg->set_global_address;
		tmp_msg.set_global_port = orig_msg->set_global_port;
		if (parse_msg(new_buf, new_len, &tmp_msg) != 0)
		{
			LM_ERR("parse_msg failed\n");
			goto error;
		}
		msg = &tmp_msg;
	} else {
		msg = orig_msg;
	}
	
	if ((msg->first_line.type != SIP_REQUEST) || (msg->via1 == 0) ||
		(msg->via1->error != PARSE_OK))
	{
		LM_CRIT("strange message: %.*s\n", msg->len, msg->buf);
		goto error;
	}
	if (exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0)
	{
		goto done;
	}

	init_run_actions_ctx(&ra_ctx);
	if (run_actions(&ra_ctx, event_rt.rlist[xhttp_route_no], msg) < 0)
	{
		ret=-1;
		LM_DBG("error while trying script\n");
		goto done;
	}

done:
	exec_post_script_cb(msg, REQUEST_CB_TYPE);
	if (msg != orig_msg)
	{
		free_sip_msg(msg);
	}
	return ret;

error:
	return -1;
}
Ejemplo n.º 6
0
/* run the error route with correct handling - simpler wrapper to 
   allow the usage from other parts of the code */
void run_error_route(struct sip_msg* msg, int force_reset)
{
	int old_route;
	LM_DBG("triggering\n");
	swap_route_type(old_route, ERROR_ROUTE);
	run_actions(error_rlist.a, msg);
	/* reset error info */
	init_err_info();
	set_route_type(old_route);
}
Ejemplo n.º 7
0
int nio_msg_received(void *data)
{
    sip_msg_t msg;
    str *obuf;
    char *nbuf = NULL;
    int_str avp_value;
    struct usr_avp *avp;
    struct run_act_ctx ra_ctx;

    obuf = (str*)data;

    if (obuf->len < nio_min_msg_len) {
        return -1;
    }

    memset(&msg, 0, sizeof(sip_msg_t));
    msg.buf = obuf->s;
    msg.len = obuf->len;

    nio_is_incoming = 1;
    init_run_actions_ctx(&ra_ctx);
    run_actions(&ra_ctx, event_rt.rlist[nio_route_no], &msg);

    if(nio_msg_avp_name.n!=0) {
        avp = NULL;
        avp=search_first_avp(nio_msg_avp_type, nio_msg_avp_name,
            &avp_value, 0);
        if(avp!=NULL && is_avp_str_val(avp)) {
            msg.buf = avp_value.s.s;
            msg.len = avp_value.s.len;
            nbuf = nio_msg_update(&msg, (unsigned int*)&obuf->len);
            if(obuf->len>=BUF_SIZE) {
                LM_ERR("new buffer overflow (%d)\n", obuf->len);
                pkg_free(nbuf);
                return -1;
            }
            memcpy(obuf->s, nbuf, obuf->len);
            obuf->s[obuf->len] = '\0';
        } else {
            LM_WARN("no value set for AVP %.*s, using unmodified message\n",
                nio_msg_avp_param.len, nio_msg_avp_param.s);
        }
    }

    if(nbuf!=NULL)
        pkg_free(nbuf);
    free_sip_msg(&msg);
    return 0;
}
Ejemplo n.º 8
0
/*! Run a request route block if it exists
 */
static int w_route_exists(struct sip_msg *msg, char *route)
{
	struct run_act_ctx ctx;
	int newroute, ret;
	str s;

	if (fixup_get_svalue(msg, (gparam_p) route, &s) != 0) {
			LM_ERR("invalid route parameter\n");
			return -1;
	}

	newroute = route_lookup(&main_rt, s.s);
	if (newroute<0) {
		return -1;
	}
	init_run_actions_ctx(&ctx);
	ret=run_actions(&ctx, main_rt.rlist[newroute], msg);
	if (ctx.run_flags & EXIT_R_F) {
		return 0;
	}
	return ret;
}
Ejemplo n.º 9
0
int nio_msg_sent(void *data)
{
    sip_msg_t msg;
    str *obuf;
    int_str avp_value;
    struct usr_avp *avp;
    struct run_act_ctx ra_ctx;

    obuf = (str*)data;

    if (obuf->len < nio_min_msg_len) {
        return -1;
    }

    memset(&msg, 0, sizeof(sip_msg_t));
    msg.buf = obuf->s;
    msg.len = obuf->len;

    nio_is_incoming = 0;
    init_run_actions_ctx(&ra_ctx);
    run_actions(&ra_ctx, event_rt.rlist[nio_route_no], &msg);

    if(nio_msg_avp_name.n!=0) {
        avp = NULL;
        avp=search_first_avp(nio_msg_avp_type, nio_msg_avp_name,
                &avp_value, 0);
        if(avp!=NULL && is_avp_str_val(avp)) {
            msg.buf = avp_value.s.s;
            msg.len = avp_value.s.len;
            obuf->s = nio_msg_update(&msg, (unsigned int*)&obuf->len);
        } else {
            LM_WARN("no value set for AVP %.*s, using unmodified message\n",
                nio_msg_avp_param.len, nio_msg_avp_param.s);
        }
    }

    free_sip_msg(&msg);
    return 0;
}
Ejemplo n.º 10
0
Archivo: action.c Proyecto: ryzhov/ATS0
int run_top_route(struct action* a, struct sip_msg* msg)
{
	int bk_action_flags;
	int bk_rec_lev;
	int ret;

	bk_action_flags = action_flags;
	bk_rec_lev = rec_lev;

	action_flags = 0;
	rec_lev = 0;
	init_err_info();
	reset_bl_markers();

	resetsflag( (unsigned int)-1 );

	run_actions(a, msg);
	ret = action_flags;

	action_flags = bk_action_flags;
	rec_lev = bk_rec_lev;

	return ret;
}
Ejemplo n.º 11
0
/* WARNING: buf must be 0 terminated (buf[len]=0) or some things might
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
{
    struct sip_msg* msg;
    int ret;
#ifdef STATS
    int skipped = 1;
    struct timeval tvb, tve;
    struct timezone tz;
    unsigned int diff;
#endif

    msg=pkg_malloc(sizeof(struct sip_msg));
    if (msg==0) {
        LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
        goto error00;
    }
    msg_no++;
    /* number of vias parsed -- good for diagnostic info in replies */
    via_cnt=0;

    memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
    /* fill in msg */
    msg->buf=buf;
    msg->len=len;
    /* zero termination (termination of orig message bellow not that
       useful as most of the work is done with scrath-pad; -jiri  */
    /* buf[len]=0; */ /* WARNING: zero term removed! */
    msg->rcv=*rcv_info;
    msg->id=msg_no;
    msg->set_global_address=default_global_address;
    msg->set_global_port=default_global_port;

    if (parse_msg(buf,len, msg)!=0) {
        LOG(L_ERR, "ERROR: receive_msg: parse_msg failed\n");
        goto error02;
    }
    DBG("After parse_msg...\n");


    /* ... clear branches from previous message */
    clear_branches();

    if (msg->first_line.type==SIP_REQUEST) {
        /* sanity checks */
        if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)) {
            /* no via, send back error ? */
            LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
            goto error;
        }
        /* check if neccesarry to add receive?->moved to forward_req */

        DBG("preparing to run routing scripts...\n");
#ifdef  STATS
        gettimeofday( & tvb, &tz );
#endif
        /* execute pre-script callbacks, if any; -jiri */
        /* if some of the callbacks said not to continue with
           script processing, don't do so
           if we are here basic sanity checks are already done
           (like presence of at least one via), so you can count
           on via1 being parsed in a pre-script callback --andrei
        */
        ret=exec_pre_cb(msg);
        if (ret<=0) {
            if (ret<0) goto error;
            else goto end; /* drop the message -- no error -- andrei */
        }
        /* exec the routing script */
        if (run_actions(rlist[0], msg)<0) {
            LOG(L_WARN, "WARNING: receive_msg: "
                "error while trying script\n");
            goto error;
        }

#ifdef STATS
        gettimeofday( & tve, &tz );
        diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
        stats->processed_requests++;
        stats->acc_req_time += diff;
        DBG("succesfully ran routing scripts...(%d usec)\n", diff);
        STATS_RX_REQUEST( msg->first_line.u.request.method_value );
#endif
    } else if (msg->first_line.type==SIP_REPLY) {
        /* sanity checks */
        if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)) {
            /* no via, send back error ? */
            LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
            goto error;
        }
#if 0
        if ((msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
            /* no second via => error? */
            LOG(L_ERR, "ERROR: receive_msg: no 2nd via found in reply\n");
            goto error;
        }
        /* check if via1 == us */
#endif

#ifdef STATS
        gettimeofday( & tvb, &tz );
        STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
#endif

        /* execute pre-script callbacks, if any; -jiri */
        /* if some of the callbacks said not to continue with
           script processing, don't do so
           if we are here basic sanity checks are already done
           (like presence of at least one via), so you can count
           on via1 being parsed in a pre-script callback --andrei
        */
        ret=exec_pre_cb(msg);
        if (ret<=0) {
            if (ret<0) goto error;
            else goto end; /* drop the message -- no error -- andrei */
        }

        /* send the msg */
        forward_reply(msg);

#ifdef STATS
        gettimeofday( & tve, &tz );
        diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
        stats->processed_responses++;
        stats->acc_res_time+=diff;
        DBG("succesfully ran reply processing...(%d usec)\n", diff);
#endif
    }
end:
#ifdef STATS
    skipped = 0;
#endif
    /* execute post-script callbacks, if any; -jiri */
    exec_post_cb(msg);
    /* free possible loaded avps -bogdan */
    reset_avps();
    DBG("receive_msg: cleaning up\n");
    free_sip_msg(msg);
    pkg_free(msg);
#ifdef STATS
    if (skipped) STATS_RX_DROPS;
#endif
    return 0;
error:
    DBG("error:...\n");
    /* execute post-script callbacks, if any; -jiri */
    exec_post_cb(msg);
    /* free possible loaded avps -bogdan */
    reset_avps();
error02:
    free_sip_msg(msg);
    pkg_free(msg);
error00:
    STATS_RX_DROPS;
    return -1;
}
Ejemplo n.º 12
0
/* WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
{
	struct sip_msg* msg;
	int ret;
#ifdef STATS
	int skipped = 1;
	struct timeval tvb, tve;	
	struct timezone tz;
	unsigned int diff;
#endif

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
		goto error00;
	}
	msg_no++;
	/* number of vias parsed -- good for diagnostic info in replies */
	via_cnt=0;

	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
	/* fill in msg */
	msg->buf=buf;
	msg->len=len;
	/* zero termination (termination of orig message bellow not that
	   useful as most of the work is done with scratch-pad; -jiri  */
	/* buf[len]=0; */ /* WARNING: zero term removed! */
	msg->rcv=*rcv_info;
	msg->id=msg_no;
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;
	
	if (parse_msg(buf,len, msg)!=0){
		LOG(L_ERR, "ERROR: receive_msg: parse_msg failed\n");
		goto error02;
	}
	DBG("After parse_msg...\n");


	/* ... clear branches from previous message */
	clear_branches();
	reset_static_buffer();

	if (msg->first_line.type==SIP_REQUEST){
		if (!IS_SIP(msg)){
			if (nonsip_msg_run_hooks(msg)!=NONSIP_MSG_ACCEPT);
				goto end; /* drop the message */
		}
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
			goto error02;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && tcp_accept_aliases && 
				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
#ifdef USE_TLS
					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
#endif
				)
			){
			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
									rcv_info->proto)!=0){
				LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
				/* continue */
			}
		}
#endif
			
	/*	skip: */
		DBG("preparing to run routing scripts...\n");
#ifdef  STATS
		gettimeofday( & tvb, &tz );
#endif
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		   script processing, don't do so
		   if we are here basic sanity checks are already done
		   (like presence of at least one via), so you can count
		   on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_req_cb(msg)==0 )
			goto end; /* drop the request */

		/* exec the routing script */
		if (run_actions(main_rt.rlist[DEFAULT_RT], msg)<0){
			LOG(L_WARN, "WARNING: receive_msg: "
					"error while trying script\n");
			goto error_req;
		}

#ifdef STATS
		gettimeofday( & tve, &tz );
		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
		stats->processed_requests++;
		stats->acc_req_time += diff;
		DBG("successfully ran routing scripts...(%d usec)\n", diff);
		STATS_RX_REQUEST( msg->first_line.u.request.method_value );
#endif

		/* execute post request-script callbacks */
		exec_post_req_cb(msg);
	}else if (msg->first_line.type==SIP_REPLY){
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
			goto error02;
		}

#ifdef STATS
		gettimeofday( & tvb, &tz );
		STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
#endif
		
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		   script processing, don't do so
		   if we are here basic sanity checks are already done
		   (like presence of at least one via), so you can count
		   on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_rpl_cb(msg)==0 )
			goto end; /* drop the request */
		/* exec the onreply routing script */
		if (onreply_rt.rlist[DEFAULT_RT]){
			ret=run_actions(onreply_rt.rlist[DEFAULT_RT], msg);
			if (ret<0){
				LOG(L_WARN, "WARNING: receive_msg: "
						"error while trying onreply script\n");
				goto error_rpl;
			}else if (ret==0) goto skip_send_reply; /* drop the message, 
													   no error */
		}
		/* send the msg */
		forward_reply(msg);
	skip_send_reply:
#ifdef STATS
		gettimeofday( & tve, &tz );
		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
		stats->processed_responses++;
		stats->acc_res_time+=diff;
		DBG("successfully ran reply processing...(%d usec)\n", diff);
#endif

		/* execute post reply-script callbacks */
		exec_post_rpl_cb(msg);
	}

end:
#ifdef STATS
	skipped = 0;
#endif
	/* free possible loaded avps -bogdan */
	reset_avps();
	DBG("receive_msg: cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
#ifdef STATS
	if (skipped) STATS_RX_DROPS;
#endif
	return 0;
error_rpl:
	/* execute post reply-script callbacks */
	exec_post_rpl_cb(msg);
	reset_avps();
	goto error02;
error_req:
	DBG("receive_msg: error:...\n");
	/* execute post request-script callbacks */
	exec_post_req_cb(msg);
	/* free possible loaded avps -bogdan */
	reset_avps();
error02:
	free_sip_msg(msg);
	pkg_free(msg);
error00:
	STATS_RX_DROPS;
	return -1;
}
Ejemplo n.º 13
0
static inline int pre_print_uac_request( struct cell *t, int branch, 
		struct sip_msg *request)
{
	int backup_route_type;
	struct usr_avp **backup_list;
	char *p;

	/* ... we calculate branch ... */
	if (!t_calc_branch(t, branch, request->add_to_branch_s,
			&request->add_to_branch_len ))
	{
		LOG(L_ERR, "ERROR:pre_print_uac_request: branch computation failed\n");
		goto error;
	}

	/* from now on, flag all new lumps with LUMPFLAG_BRANCH flag in order to
	 * be able to remove them later --bogdan */
	set_init_lump_flags(LUMPFLAG_BRANCH);

	/********** run route & callback ************/

	/* run branch route, if any; run it before RURI's DNS lookup 
	 * to allow to be changed --bogdan */
	if (t->on_branch) {
		/* need to pkg_malloc the dst_uri */
		if ( request->dst_uri.len ) {
			if ( (p=pkg_malloc(request->dst_uri.len))==0 ) {
				LOG(L_ERR,"ERROR:tm:pre_print_uac_request: no more pkg mem\n");
				ser_error=E_OUT_OF_MEM;
				goto error;
			}
			memcpy( p, request->dst_uri.s, request->dst_uri.len);
			request->dst_uri.s = p;
		}
		/* need to pkg_malloc the new_uri */
		if ( (p=pkg_malloc(request->new_uri.len))==0 ) {
			LOG(L_ERR,"ERROR:tm:pre_print_uac_request: no more pkg mem\n");
			ser_error=E_OUT_OF_MEM;
			goto error;
		}
		memcpy( p, request->new_uri.s, request->new_uri.len);
		request->new_uri.s = p;
		/* make available the avp list from transaction */
		backup_list = set_avp_list( &t->user_avps );
		/* run branch route */
		swap_route_type( backup_route_type, BRANCH_ROUTE);
		if (run_actions(branch_rlist[t->on_branch], request)==0 &&
		(action_flags&ACT_FL_DROP) ) {
			DBG("DEBUG:tm:pre_print_uac_request: dropping branch <%.*s>\n",
				request->dst_uri.len, request->dst_uri.s);
			goto error;
		}
		set_route_type( backup_route_type );
		/* restore original avp list */
		set_avp_list( backup_list );
	}

	/* run the specific callbacks for this transaction */
	run_trans_callbacks( TMCB_REQUEST_FWDED, t, request, 0,
			-request->REQ_METHOD);

	return 0;
error:
	return -1;
}
Ejemplo n.º 14
0
/* forwards the msg to the given location set; if flags has set the
 * CPL_PROXY_DONE, all locations will be added as branches, otherwise, the first
 * one will set as RURI (this is ha case when this is the first proxy of the
 * message)
 * The given list of location will be freed, returning 0 instead.
 * Returns:  0 - OK
 *          -1 - error */
int cpl_proxy_to_loc_set( struct sip_msg *msg, struct location **locs,
													unsigned char flag)
{
	struct location *foo;
	struct action act;

	if (!*locs) {
		LOG(L_ERR,"ERROR:cpl_c:cpl_proxy_to_loc_set: empty loc set!!\n");
		goto error;
	}

	/* if it's the first time when this sip_msg is proxied, use the first addr
	 * in loc_set to rewrite the RURI */
	if (!(flag&CPL_PROXY_DONE)) {
		DBG("DEBUG:cpl_c:cpl_proxy_to_loc_set: rewriting Request-URI with "
			"<%s>\n",(*locs)->addr.uri.s);
		/* build a new action for setting the URI */
		memset(&act, 0, sizeof(act));
		act.type = SET_URI_T;
		act.val[0].type = STRING_ST;
		act.val[0].u.string = (*locs)->addr.uri.s;
		act.next = 0;
		/* push the action */
		if (do_action(&act, msg) < 0) {
			LOG(L_ERR,"ERROR:cpl_c:cpl_proxy_to_loc_set: do_action failed\n");
			goto error;
		}
		/* is the location NATED? */
		if ((*locs)->flags&CPL_LOC_NATED) setflag(msg,cpl_env.nat_flag);
		/* free the location and point to the next one */
		foo = (*locs)->next;
		free_location( *locs );
		*locs = foo;
	}

	/* add the rest of the locations as branches */
	while(*locs) {
		DBG("DEBUG:cpl_c:cpl_proxy_to_loc_set: appending branch "
			"<%.*s>\n",(*locs)->addr.uri.len,(*locs)->addr.uri.s);
		if(append_branch(msg,(*locs)->addr.uri.s,(*locs)->addr.uri.len,0, 0, Q_UNSPECIFIED, 0)==-1){
			LOG(L_ERR,"ERROR:cpl_c:cpl_proxy_to_loc_set: failed when "
				"appending branch <%s>\n",(*locs)->addr.uri.s);
			goto error;
		}
		/* is the location NATED? */
		if ((*locs)->flags&CPL_LOC_NATED) setflag(msg,cpl_env.nat_flag);
		/* free the location and point to the next one */
		foo = (*locs)->next;
		free_location( *locs );
		*locs = foo;
	}

	/* run what proxy route is set */
	if (cpl_env.proxy_route) {
		if (run_actions( main_rt.rlist[cpl_env.proxy_route], msg)<0) {
			LOG(L_ERR,"ERROR:cpl_c:cpl_proxy_to_loc_set: "
				"Error in do_action for proxy_route\n");
		}
	}

	/* do t_forward */
	if ( flag&CPL_IS_STATEFUL ) {
		/* transaction exists */
		if (cpl_fct.tmb.t_forward_nonack(msg, 0/*no proxy*/)==-1) {
			LOG(L_ERR,"ERROR:cpl_c:cpl_proxy_to_loc_set: t_forward_nonack "
				"failed !\n");
			goto error;
		}
	} else {
		/* no transaction -> build & fwd */
		if (cpl_fct.tmb.t_relay(msg, 0, 0)==-1) {
			LOG(L_ERR,"ERROR:cpl_c:cpl_proxy_to_loc_set: t_relay failed !\n");
			goto error;
		}
	}

	return 0;
error:
	return -1;
}
Ejemplo n.º 15
0
/* ret= 0! if action -> end of list(e.g DROP), 
      > 0 to continue processing next actions
   and <0 on error */
int do_action(struct action* a, struct sip_msg* msg)
{
	int ret;
	int v;
	int sec,usec;
	union sockaddr_union* to;
	struct proxy_l* p;
	char* tmp;
	char *new_uri, *end, *crt;
	int len,i;
	int user = 0;
	int expires = 0;
	str vals[5];
	str result;
	struct sip_uri uri, next_hop;
	struct sip_uri *u;
	unsigned short port;
	int cmatch;
	struct action *aitem;
	struct action *adefault;
	pv_spec_t *spec;
	pv_elem_p model;
	pv_value_t val;
	pv_elem_t *pve;
	str name_s;
	struct timeval start;
	int end_time;
	action_elem_t *route_params_bak;
	int route_params_number_bak;

	/* reset the value of error to E_UNSPEC so avoid unknowledgable
	   functions to return with error (status<0) and not setting it
	   leaving there previous error; cache the previous value though
	   for functions which want to process it */
	prev_ser_error=ser_error;
	ser_error=E_UNSPEC;

	start_expire_timer(start,execmsgthreshold);

	ret=E_BUG;
	switch ((unsigned char)a->type){
		case DROP_T:
				script_trace("core", "drop", msg, a->line) ;
				action_flags |= ACT_FL_DROP;
		case EXIT_T:
				script_trace("core", "exit", msg, a->line) ;
				ret=0;
				action_flags |= ACT_FL_EXIT;
			break;
		case RETURN_T:
				script_trace("core", "return", msg, a->line) ;
				if (a->elem[0].type == SCRIPTVAR_ST)
				{
					spec = (pv_spec_t*)a->elem[0].u.data;
					if(pv_get_spec_value(msg, spec, &val)!=0
						|| (val.flags&PV_VAL_NULL))
					{
						ret=-1;
					} else {
						if(!(val.flags&PV_VAL_INT))
							ret = 1;
						else
							ret = val.ri;
					}
					pv_value_destroy(&val);
				} else {
					ret=a->elem[0].u.number;
				}
				action_flags |= ACT_FL_RETURN;
			break;
		case FORWARD_T:
			script_trace("core", "forward", msg, a->line) ;
			if (a->elem[0].type==NOSUBTYPE){
				/* parse uri and build a proxy */
				if (msg->dst_uri.len) {
					ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
						&next_hop);
					u = &next_hop;
				} else {
					ret = parse_sip_msg_uri(msg);
					u = &msg->parsed_uri;
				}
				if (ret<0) {
					LM_ERR("forward: bad_uri dropping packet\n");
					break;
				}
				/* create a temporary proxy*/
				p=mk_proxy(u->maddr_val.len?&u->maddr_val:&u->host,
					u->port_no, u->proto, (u->type==SIPS_URI_T)?1:0 );
				if (p==0){
					LM_ERR("bad host name in uri, dropping packet\n");
					ret=E_BAD_ADDRESS;
					goto error_fwd_uri;
				}
				ret=forward_request(msg, p);
				free_proxy(p); /* frees only p content, not p itself */
				pkg_free(p);
				if (ret==0) ret=1;
			}else if ((a->elem[0].type==PROXY_ST)) {
				ret=forward_request(msg,(struct proxy_l*)a->elem[0].u.data);
				if (ret==0) ret=1;
			}else{
				LM_ALERT("BUG in forward() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
			}
			break;
		case SEND_T:
			script_trace("core", "send", msg, a->line) ;
			if (a->elem[0].type!= PROXY_ST){
				LM_ALERT("BUG in send() type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if (a->elem[1].u.data) {
				if (a->elem[1].type != SCRIPTVAR_ELEM_ST){
					LM_ALERT("BUG in send() header type %d\n",a->elem[1].type);
					ret=E_BUG;
					break;
				} else {
					pve = (pv_elem_t *)a->elem[1].u.data;
				}
			} else {
				pve = NULL;
			}
			to=(union sockaddr_union*)
					pkg_malloc(sizeof(union sockaddr_union));
			if (to==0){
				LM_ERR("memory allocation failure\n");
				ret=E_OUT_OF_MEM;
				break;
			}
			
			p=(struct proxy_l*)a->elem[0].u.data;
			
			ret=hostent2su(to, &p->host, p->addr_idx,
						(p->port)?p->port:SIP_PORT );
			if (ret==0){
				if (pve) {
					if ( pv_printf_s(msg, pve, &name_s)!=0 || 
							name_s.len == 0 || name_s.s == NULL) {
						LM_WARN("cannot get string for value\n");
						ret=E_UNSPEC;
						break;
					}
					/* build new msg */
					tmp = pkg_malloc(msg->len + name_s.len);
					if (!tmp) {
						LM_ERR("memory allocation failure\n");
						ret = E_OUT_OF_MEM;
						break;
					}
					LM_DBG("searching for first line %d\n",
							msg->first_line.len);
					/* search first line of previous msg */
					/* copy headers */
					len = msg->first_line.len;
					memcpy(tmp, msg->buf, len);
					memcpy(tmp + len, name_s.s, name_s.len);
					memcpy(tmp + len + name_s.len,
							msg->buf + len, msg->len - len);
					ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/,
							tmp, msg->len + name_s.len);
					pkg_free(tmp);
				} else {
					ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/,
							msg->buf, msg->len);
				}
				if (ret!=0 && p->host.h_addr_list[p->addr_idx+1])
					p->addr_idx++;
			}
			pkg_free(to);
			if (ret==0)
				ret=1;
			break;
		case LOG_T:
			script_trace("core", "log", msg, a->line) ;
			if ((a->elem[0].type!=NUMBER_ST)|(a->elem[1].type!=STRING_ST)){
				LM_ALERT("BUG in log() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
				break;
			}
			LM_GEN1(a->elem[0].u.number, "%s", a->elem[1].u.string);
			ret=1;
			break;
		case APPEND_BRANCH_T:
			script_trace("core", "append_branch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in append_branch %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[0].u.s.s==NULL) {
				ret = append_branch(msg, 0, &msg->dst_uri, &msg->path_vec,
					get_ruri_q(), getb0flags(), msg->force_send_socket);
				/* reset all branch info */
				msg->force_send_socket = 0;
				setb0flags(0);
				set_ruri_q(Q_UNSPECIFIED);
				if(msg->dst_uri.s!=0)
					pkg_free(msg->dst_uri.s);
				msg->dst_uri.s = 0;
				msg->dst_uri.len = 0;
				if(msg->path_vec.s!=0)
					pkg_free(msg->path_vec.s);
				msg->path_vec.s = 0;
				msg->path_vec.len = 0;
			} else {
				ret = append_branch(msg, &a->elem[0].u.s, &msg->dst_uri, 
					&msg->path_vec, a->elem[1].u.number, getb0flags(),
					msg->force_send_socket);
			}
			break;
		case REMOVE_BRANCH_T:
			script_trace("core", "remove_branch", msg, a->line) ;
			if (a->elem[0].type == SCRIPTVAR_ST) {
				spec = (pv_spec_t*)a->elem[0].u.data;
				if( pv_get_spec_value(msg, spec, &val)!=0
				|| (val.flags&PV_VAL_NULL) || !(val.flags&PV_VAL_INT) ) {
					ret=-1;
					break;
				}
				i = val.ri;
			} else {
				i=a->elem[0].u.number;
			}
			ret = (remove_branch((unsigned int)i)==0)?1:-1;
			break;
		case LEN_GT_T:
			script_trace("core", "len_gt", msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST) {
				LM_ALERT("BUG in len_gt type %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			ret = (msg->len >= (unsigned int)a->elem[0].u.number) ? 1 : -1;
			break;
		case SET_DEBUG_T:
			script_trace("core", "set_debug", msg, a->line) ;
			if (a->elem[0].type==NUMBER_ST)
				set_proc_debug_level(a->elem[0].u.number);
			else
				reset_proc_debug_level();
			ret = 1;
			break;
		case SETFLAG_T:
			script_trace("core", "setflag", msg, a->line) ;
			ret = setflag( msg, a->elem[0].u.number );
			break;
		case RESETFLAG_T:
			script_trace("core", "resetflag", msg, a->line) ;
			ret = resetflag( msg, a->elem[0].u.number );
			break;
		case ISFLAGSET_T:
			script_trace("core", "isflagset", msg, a->line) ;
			ret = isflagset( msg, a->elem[0].u.number );
			break;
		case SETSFLAG_T:
			script_trace("core", "setsflag", msg, a->line) ;
			ret = setsflag( a->elem[0].u.number );
			break;
		case RESETSFLAG_T:
			script_trace("core", "resetsflag", msg, a->line) ;
			ret = resetsflag( a->elem[0].u.number );
			break;
		case ISSFLAGSET_T:
			script_trace("core", "issflagset", msg, a->line) ;
			ret = issflagset( a->elem[0].u.number );
			break;
		case SETBFLAG_T:
			script_trace("core", "setbflag", msg, a->line) ;
			ret = setbflag( a->elem[0].u.number, a->elem[1].u.number );
			break;
		case RESETBFLAG_T:
			script_trace("core", "resetbflag", msg, a->line) ;
			ret = resetbflag( a->elem[0].u.number, a->elem[1].u.number  );
			break;
		case ISBFLAGSET_T:
			script_trace("core", "isbflagset", msg, a->line) ;
			ret = isbflagset( a->elem[0].u.number, a->elem[1].u.number  );
			break;
		case ERROR_T:
			script_trace("core", "error", msg, a->line) ;
			if ((a->elem[0].type!=STRING_ST)|(a->elem[1].type!=STRING_ST)){
				LM_ALERT("BUG in error() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
				break;
			}
			LM_ERR("error(\"%s\", \"%s\") not implemented yet\n",
				a->elem[0].u.string, a->elem[1].u.string);
			ret=1;
			break;
		case ROUTE_T:
			script_trace("route", rlist[a->elem[0].u.number].name, msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST){
				LM_ALERT("BUG in route() type %d\n",
						a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if ((a->elem[0].u.number>RT_NO)||(a->elem[0].u.number<0)){
				LM_ALERT("BUG - invalid routing table number in"
							"route(%lu)\n", a->elem[0].u.number);
				ret=E_CFG;
				break;
			}
			/* check if the route has parameters */
			if (a->elem[1].type != 0) {
				if (a->elem[1].type != NUMBER_ST || a->elem[2].type != SCRIPTVAR_ELEM_ST) {
					LM_ALERT("BUG in route() type %d/%d\n",
							a->elem[1].type, a->elem[2].type);
					ret=E_BUG;
					break;
				}
				route_params_bak = route_params;
				route_params = (action_elem_t *)a->elem[2].u.data;
				route_params_number_bak = route_params_number;
				route_params_number = a->elem[1].u.number;

				return_code=run_actions(rlist[a->elem[0].u.number].a, msg);
				route_params = route_params_bak;
				route_params_number = route_params_number_bak;
			} else {
				return_code=run_actions(rlist[a->elem[0].u.number].a, msg);
			}
			ret=return_code;
			break;
		case REVERT_URI_T:
			script_trace("core", "revert_uri", msg, a->line) ;
			if (msg->new_uri.s) {
				pkg_free(msg->new_uri.s);
				msg->new_uri.len=0;
				msg->new_uri.s=0;
				msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
			};
			ret=1;
			break;
		case SET_HOST_T:
		case SET_HOSTPORT_T:
		case SET_USER_T:
		case SET_USERPASS_T:
		case SET_PORT_T:
		case SET_URI_T:
		case PREFIX_T:
		case STRIP_T:
		case STRIP_TAIL_T:
				script_trace("core", 
					(unsigned char)a->type == SET_HOST_T     ? "set_host" :
					(unsigned char)a->type == SET_HOSTPORT_T ? "set_hostport" : 
					(unsigned char)a->type == SET_USER_T     ? "set_user" :
					(unsigned char)a->type == SET_USERPASS_T ? "set_userpass" : 
					(unsigned char)a->type == SET_PORT_T     ? "set_port" :
					(unsigned char)a->type == SET_URI_T      ? "set_uri" : 
					(unsigned char)a->type == PREFIX_T       ? "prefix" :
					(unsigned char)a->type == STRIP_T  ? "strip" : "strip_tail",
					msg, a->line);
				user=0;
				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
					if (a->elem[0].type!=NUMBER_ST) {
						LM_ALERT("BUG in set*() type %d\n",
							a->elem[0].type);
						break;
					}
				} else if (a->elem[0].type!=STR_ST){
					LM_ALERT("BUG in set*() type %d\n",
							a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (a->type==SET_URI_T) {
					if (set_ruri( msg, &a->elem[0].u.s) ) {
						LM_ERR("failed to set new RURI\n");
						ret=E_OUT_OF_MEM;
						break;
					}
					ret=1;
					break;
				}
				if (msg->new_uri.s) {
					tmp=msg->new_uri.s;
					len=msg->new_uri.len;
				}else{
					tmp=msg->first_line.u.request.uri.s;
					len=msg->first_line.u.request.uri.len;
				}
				if (parse_uri(tmp, len, &uri)<0){
					LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp);
					ret=E_UNSPEC;
					break;
				}
				
				new_uri=pkg_malloc(MAX_URI_SIZE);
				if (new_uri==0){
					LM_ERR("memory allocation failure\n");
					ret=E_OUT_OF_MEM;
					break;
				}
				end=new_uri+MAX_URI_SIZE;
				crt=new_uri;
				/* begin copying */
				len = (uri.user.len?uri.user.s:uri.host.s) - tmp;
				if (crt+len>end) goto error_uri;
				memcpy(crt,tmp,len);crt+=len;

				if (a->type==PREFIX_T) {
					if (crt+a->elem[0].u.s.len>end) goto error_uri;
					memcpy( crt, a->elem[0].u.s.s, a->elem[0].u.s.len);
					crt+=a->elem[0].u.s.len;
					/* whatever we had before, with prefix we have username 
					   now */
					user=1;
				}

				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else if (a->type==STRIP_T) {
					if (a->elem[0].u.number>uri.user.len) {
						LM_WARN("too long strip asked; "
								" deleting username: %lu of <%.*s>\n",
								a->elem[0].u.number, uri.user.len, uri.user.s);
						len=0;
					} else if (a->elem[0].u.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s + a->elem[0].u.number;
						len=uri.user.len - a->elem[0].u.number;
					}
				} else if (a->type==STRIP_TAIL_T) {
					if (a->elem[0].u.number>uri.user.len) {
						LM_WARN("too long strip_tail asked;"
								" deleting username: %lu of <%.*s>\n",
								a->elem[0].u.number, uri.user.len, uri.user.s);
						len=0;
					} else if (a->elem[0].u.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s;
						len=uri.user.len - a->elem[0].u.number;
					}
				} else {
					tmp=uri.user.s;
					len=uri.user.len;
				}

				if (len){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
					user=1; /* we have an user field so mark it */
				}

				if (a->type==SET_USERPASS_T) tmp=0;
				else tmp=uri.passwd.s;
				/* passwd */
				if (tmp){
					len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* host */
				if (user || tmp){ /* add @ */
					if(crt+1>end) goto error_uri;
					*crt='@'; crt++;
				}
				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else {
					tmp=uri.host.s;
					len = uri.host.len;
				}
				if (tmp){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* port */
				if (a->type==SET_HOSTPORT_T) tmp=0;
				else if (a->type==SET_PORT_T) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else {
					tmp=uri.port.s;
					len = uri.port.len;
				}
				if (tmp && len>0){
					if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* params */
				tmp=uri.params.s;
				if (tmp){
					/* include in param string the starting ';' */
					len=uri.params.len+1;
					tmp--;
					if(crt+len+1>end) goto error_uri;
					/* if a maddr param is present, strip it out */
					if (uri.maddr.len &&
					(a->type==SET_HOSTPORT_T || a->type==SET_HOST_T)) {
						memcpy(crt,tmp,uri.maddr.s-tmp-1);
						crt+=uri.maddr.s-tmp-1;
						memcpy(crt,uri.maddr_val.s+uri.maddr_val.len,
							tmp+len-uri.maddr_val.s-uri.maddr_val.len);
						crt+=tmp+len-uri.maddr_val.s-uri.maddr_val.len;
					} else {
						memcpy(crt,tmp,len);crt+=len;
					}
				}
				/* headers */
				tmp=uri.headers.s;
				if (tmp){
					len=uri.headers.len; if(crt+len+1>end) goto error_uri;
					*crt='?'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				*crt=0; /* null terminate the thing */
				/* copy it to the msg */
				if (msg->new_uri.s) pkg_free(msg->new_uri.s);
				msg->new_uri.s=new_uri;
				msg->new_uri.len=crt-new_uri;
				msg->parsed_uri_ok=0;
				ret=1;
				break;
		case SET_DSTURI_T:
			script_trace("core", "set_dsturi", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in setdsturi() type %d\n",
							a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if(set_dst_uri(msg, &a->elem[0].u.s)!=0)
				ret = -1;
			else
				ret = 1;
			break;
		case SET_DSTHOST_T:
		case SET_DSTPORT_T:
			script_trace("core", (unsigned char) a->type == SET_DSTHOST_T ?
						 "set_dsturi" : "set_dstport", msg, a->line);
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in domain setting type %d\n",
							a->elem[0].type);
				ret=E_BUG;
				break;
			}

			tmp = msg->dst_uri.s;
			len = msg->dst_uri.len;

			if (tmp == NULL || len == 0) {
				LM_ERR("failure - null uri\n");
				ret = E_UNSPEC;
				break;
			}
			if (a->type == SET_DSTHOST_T &&
					(a->elem[0].u.s.s == NULL || a->elem[0].u.s.len == 0)) {
				LM_ERR("cannot set a null uri domain\n");
				break;
			}
			if (parse_uri(tmp, len, &uri)<0) {
				LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp);
				break;
			}
			new_uri=pkg_malloc(MAX_URI_SIZE);
			if (new_uri == NULL) {
				LM_ERR("memory allocation failure\n");
				ret=E_OUT_OF_MEM;
				break;
			}
			end=new_uri+MAX_URI_SIZE;
			crt=new_uri;
			len = (uri.user.len?uri.user.s:uri.host.s) - tmp;
			if (crt+len>end) goto error_uri;
			memcpy(crt,tmp,len);
			crt += len;
			/* user */
			tmp = uri.user.s;
			len = uri.user.len;
			if (tmp) {
				if (crt+len>end) goto error_uri;
				memcpy(crt,tmp,len);
				crt += len;
				user = 1;
			}
			/* passwd */
			tmp = uri.passwd.s;
			len = uri.passwd.len;
			if (user || tmp) {
				if (crt+len+1>end) goto error_uri;
				*crt++=':';
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* host */
			if (a->type==SET_DSTHOST_T) {
				tmp = a->elem[0].u.s.s;
				len = a->elem[0].u.s.len;
			} else {
				tmp = uri.host.s;
				len = uri.host.len;
			}
			if (tmp) {
				if (user) {
					if (crt+1>end) goto error_uri;
					*crt++='@';
				}
				if (crt+len+1>end) goto error_uri;
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* port */
			if (a->type==SET_DSTPORT_T) {
				tmp = a->elem[0].u.s.s;
				len = a->elem[0].u.s.len;
			} else {
				tmp = uri.port.s;
				len = uri.port.len;
			}
			if (tmp) {
				if (crt+len+1>end) goto error_uri;
				*crt++=':';
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* params */
			tmp=uri.params.s;
			if (tmp){
				len=uri.params.len; if(crt+len+1>end) goto error_uri;
				*crt++=';';
				memcpy(crt,tmp,len);
				crt += len;
			}
			/* headers */
			tmp=uri.headers.s;
			if (tmp){
				len=uri.headers.len; if(crt+len+1>end) goto error_uri;
				*crt++='?';
				memcpy(crt,tmp,len);
				crt += len;
			}
			*crt=0; /* null terminate the thing */
			/* copy it to the msg */
			pkg_free(msg->dst_uri.s);
			msg->dst_uri.s=new_uri;
			msg->dst_uri.len=crt-new_uri;
			ret = 1;
			break;
		case RESET_DSTURI_T:
			script_trace("core", "reset_dsturi", msg, a->line) ;
			if(msg->dst_uri.s!=0)
				pkg_free(msg->dst_uri.s);
			msg->dst_uri.s = 0;
			msg->dst_uri.len = 0;
			ret = 1;
			break;
		case ISDSTURISET_T:
			script_trace("core", "isdsturiset", msg, a->line) ;
			if(msg->dst_uri.s==0 || msg->dst_uri.len<=0)
				ret = -1;
			else
				ret = 1;
			break;
		case IF_T:
			script_trace("core", "if", msg, a->line) ;
				/* if null expr => ignore if? */
				if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){
					v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0);
					/* set return code to expr value */
					if (v<0 || (action_flags&ACT_FL_RETURN)
							|| (action_flags&ACT_FL_EXIT) ){
						if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){ /* hack to quit on DROP*/
							ret=0;
							return_code = 0;
							break;
						}else{
							LM_WARN("error in expression (l=%d)\n", a->line);
						}
					}
					
					ret=1;  /*default is continue */
					if (v>0) {
						if ((a->elem[1].type==ACTIONS_ST)&&a->elem[1].u.data){
							ret=run_action_list(
									(struct action*)a->elem[1].u.data,msg );
							return_code = ret;
						} else return_code = v;
					}else{
						if ((a->elem[2].type==ACTIONS_ST)&&a->elem[2].u.data){
							ret=run_action_list(
								(struct action*)a->elem[2].u.data,msg);
							return_code = ret;
						} else return_code = v;
					}
				}
			break;
		case WHILE_T:
			script_trace("core", "while", msg, a->line) ;
				/* if null expr => ignore if? */
				if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){
					len = 0;
					while(1)
					{
						if(len++ >= max_while_loops)
						{
							LM_INFO("max while loops are encountered\n");
							break;
						}
						v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0);
						/* set return code to expr value */
						if (v<0 || (action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){
							if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN)
									|| (action_flags&ACT_FL_EXIT) ){
								ret=0;
								return_code = 0;
								break;
							}else{
								LM_WARN("error in expression (l=%d)\n",
										a->line);
							}
						}
					
						ret=1;  /*default is continue */
						if (v>0) {
							if ((a->elem[1].type==ACTIONS_ST)
									&&a->elem[1].u.data){
								ret=run_action_list(
									(struct action*)a->elem[1].u.data,msg );
								/* check if return was done */
								if ((action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){
									break;
								}
								return_code = ret;
							} else {
								/* we should not get here */
								return_code = v;
								break;
							}
						} else {
							/* condition was false */
							return_code = v;
							break;
						}
					}
				}
			break;
		case CACHE_STORE_T:
			script_trace("core", "cache_store", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[2].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store() - third argument not of type"
						" string%d\n", a->elem[2].type );
				ret=E_BUG;
				break;
			}

			str val_s;

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			/* parse the value argument */
			pve = (pv_elem_t *)a->elem[2].u.data;
			if ( pv_printf_s(msg, pve, &val_s)!=0 || 
			val_s.len == 0 || val_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			/* get the expires value */
			if ( a->elem[3].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[3].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_store\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_store expires, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				expires = val.ri;
			}
			else
			if ( a->elem[3].type == NUMBER_ST )
			{
				expires = (int)a->elem[3].u.number;
			}

			ret = cachedb_store( &a->elem[0].u.s, &name_s, &val_s,expires);

			break;
		case CACHE_REMOVE_T:
			script_trace("core", "cache_remove", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_remove() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_remove() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}
			ret = cachedb_remove( &a->elem[0].u.s, &name_s);
			break;
		case CACHE_FETCH_T:
			script_trace("core", "cache_fetch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in cache_fetch() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			str aux = {0, 0};
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			ret = cachedb_fetch( &a->elem[0].u.s, &name_s, &aux);
			if(ret > 0)
			{
				val.rs = aux;
				val.flags = PV_VAL_STR;

				spec = (pv_spec_t*)a->elem[2].u.data;
				if (pv_set_value(msg, spec, 0, &val) < 0) {
					LM_ERR("cannot set the variable value\n");
					pkg_free(aux.s);
					return -1;
				}
				pkg_free(aux.s);
			}
			
			break;
		case CACHE_COUNTER_FETCH_T:
			script_trace("core", "cache_counter_fetch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in cache_fetch() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			int aux_counter;
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			ret = cachedb_counter_fetch( &a->elem[0].u.s, &name_s, &aux_counter);
			if(ret > 0)
			{
				val.ri = aux_counter;
				val.flags = PV_TYPE_INT|PV_VAL_INT;

				spec = (pv_spec_t*)a->elem[2].u.data;
				if (pv_set_value(msg, spec, 0, &val) < 0) {
					LM_ERR("cannot set the variable value\n");
					pkg_free(aux.s);
					return -1;
				}
			}
			break;
		case CACHE_ADD_T:
			script_trace("core", "cache_add", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_add() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_add()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			int increment=0;

			/* get the increment value */
			if ( a->elem[2].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[2].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_add\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_add, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				increment = val.ri;
			}
			else if ( a->elem[2].type == NUMBER_ST )
			{
				increment = (int)a->elem[2].u.number;
			}

			expires = (int)a->elem[3].u.number;

			/* TODO - return the new value to script ? */
			ret = cachedb_add(&a->elem[0].u.s, &name_s, increment,expires,NULL);
			break;
		case CACHE_SUB_T:
			script_trace("core", "cache_sub", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_sub() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_sub()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			int decrement=0;

			/* get the increment value */
			if ( a->elem[2].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[2].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_sub\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_sub, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				decrement = val.ri;
			}
			else if ( a->elem[2].type == NUMBER_ST )
			{
				decrement = (int)a->elem[2].u.number;
			}

			expires = (int)a->elem[3].u.number;

			/* TODO - return new value to script ? */
			ret = cachedb_sub(&a->elem[0].u.s, &name_s, decrement,expires,NULL);
			break;
		case CACHE_RAW_QUERY_T:
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data != NULL && 
				a->elem[2].type!=STR_ST){
				LM_ALERT("BUG in cache_raw_query() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			cdb_raw_entry **cdb_reply;
			int val_number=0,i,j;
			int key_number=0;
			pvname_list_t *cdb_res,*it;
			int_str avp_val;
			int_str avp_name;
			unsigned short avp_type;

			if (a->elem[2].u.data) {
				cdb_res = (pvname_list_t*)a->elem[2].u.data;
				for (it=cdb_res;it;it=it->next)
					val_number++;

				LM_DBG("The query expects %d results back\n",val_number);

				ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, &cdb_reply,val_number,&key_number);
				if (ret >= 0 && val_number > 0) {
					for (i=key_number-1; i>=0;i--) {
						it=cdb_res;
						for (j=0;j < val_number;j++) {
							avp_type = 0;
							if (pv_get_avp_name(msg,&it->sname.pvp,&avp_name.n,
								&avp_type) != 0) {
								LM_ERR("cannot get avp name [%d/%d]\n",i,j);
								goto next_avp;
							}
							
							switch (cdb_reply[i][j].type) {
								case CDB_INT:
									avp_val.n = cdb_reply[i][j].val.n; 
									break;
								case CDB_STR:
									avp_type |= AVP_VAL_STR;
									avp_val.s = cdb_reply[i][j].val.s;
									break;
								default:
									LM_WARN("Unknown type %d\n",cdb_reply[i][j].type);
									goto next_avp;
							}
							if (add_avp(avp_type,avp_name.n,avp_val) != 0) {
								LM_ERR("Unable to add AVP\n");
								free_raw_fetch(cdb_reply,val_number,key_number);
								return -1;
							}
next_avp:
							if (it) {
								it = it->next;
								if (it==NULL);
									break;
							}
						}
					}
					free_raw_fetch(cdb_reply,val_number,key_number);
				}
			}
			else
				ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, NULL,0,NULL);
			break;
		case XDBG_T:
			script_trace("core", "xdbg", msg, a->line) ;
			if (a->elem[0].type == SCRIPTVAR_ELEM_ST)
			{
				if (xdbg(msg, a->elem[0].u.data, val.rs.s) < 0)
				{
					LM_ALERT("Cannot print message");
					break;
				}
			}
			else
			{
				LM_ALERT("BUG in xdbg() type %d\n", a->elem[0].type);
				ret=E_BUG;
			}
			break;
		case XLOG_T:
			script_trace("core", "xlog", msg, a->line) ;
			if (a->elem[1].u.data != NULL)
			{
				if (a->elem[1].type != SCRIPTVAR_ELEM_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[1].type);
					ret=E_BUG;
					break;
				}
				if (a->elem[0].type != STR_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (xlog_2(msg,a->elem[0].u.data, a->elem[1].u.data) < 0)
				{
					LM_ALERT("Cannot print xlog debug message");
					break;
				}
			}
			else
			{
				if (a->elem[0].type != SCRIPTVAR_ELEM_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (xlog_1(msg,a->elem[0].u.data, val.rs.s) < 0)
				{
					LM_ALERT("Cannot print xlog debug message");
					break;
				}
			}

			break;
		case RAISE_EVENT_T:
			script_trace("core", "raise_event", msg, a->line) ;
			if (a->elem[0].type != NUMBER_ST) {
				LM_ERR("invalid event id\n");
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data) {
				/* three parameters specified */
				ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number,
						a->elem[1].u.data, a->elem[2].u.data);
			} else {
				/* two parameters specified */
				ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number,
						NULL, a->elem[1].u.data);
			}
			if (ret <= 0) {
				LM_ERR("cannot raise event\n");
				ret=E_UNSPEC;
				break;
			}
			break;
		case SUBSCRIBE_EVENT_T:
			script_trace("core", "subscribe_event", msg, a->line) ;
			if (a->elem[0].type != STR_ST || a->elem[1].type != STR_ST) {
				LM_ERR("BUG in subscribe arguments\n");
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data) {
				if (a->elem[2].type != NUMBER_ST) {
					LM_ERR("BUG in subscribe expiration time\n");
					ret=E_BUG;
					break;
				} else {
					i = a->elem[2].u.number;
				}
			} else {
				i = 0;
			}

			name_s.s = a->elem[0].u.data;
			name_s.len = strlen(name_s.s);
			/* result should be the socket */
			result.s = a->elem[1].u.data;
			result.len = strlen(result.s);
			ret = evi_event_subscribe(name_s, result, i, 0);
			break;

		case CONSTRUCT_URI_T:
			script_trace("core", "construct_uri", msg, a->line) ;
			for (i=0;i<5;i++)
			{
				pve = (pv_elem_t *)a->elem[i].u.data;
				if (pve->spec.getf)
				{
					if ( pv_printf_s(msg, pve, &vals[i])!=0 || 
						vals[i].len == 0 || vals[i].s == NULL) 
					{
						LM_WARN("cannot get string for value\n");
						ret=E_BUG;
						return -1;
					}
				}
				else
					vals[i] = pve->text;
			}
			
			result.s = construct_uri(&vals[0],&vals[1],&vals[2],&vals[3],&vals[4],
					&result.len);

			if (result.s)
			{
				int_str res;
				int avp_name;
				unsigned short avp_type;

				spec = (pv_spec_t*)a->elem[5].u.data;
				if (pv_get_avp_name( msg, &(spec->pvp), &avp_name,
						&avp_type)!=0){
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.s = result;
				if (add_avp(AVP_VAL_STR|avp_type, avp_name, res)<0){
					LM_ERR("cannot add AVP\n");
					return -1;
				}
			}

			break;
		case GET_TIMESTAMP_T:
			script_trace("core", "get_timestamp", msg, a->line) ;
			if (get_timestamp(&sec,&usec) == 0) {
				int avp_name;
				int_str res;
				unsigned short avp_type;

				spec = (pv_spec_t*)a->elem[0].u.data;
				if (pv_get_avp_name(msg, &(spec->pvp), &avp_name,
						&avp_type) != 0) {
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.n = sec;
				if (add_avp(avp_type, avp_name, res) < 0) {
					LM_ERR("cannot add AVP\n");
					return -1;
				}

				spec = (pv_spec_t*)a->elem[1].u.data;
				if (pv_get_avp_name(msg, &(spec->pvp), &avp_name,
						&avp_type) != 0) {
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.n = usec;
				if (add_avp(avp_type, avp_name, res) < 0) {
					LM_ERR("cannot add AVP\n");
					return -1;
				}
			} else {
				LM_ERR("failed to get time\n");
				return -1;
			}
			break;
		case SWITCH_T:
			script_trace("core", "switch", msg, a->line) ;
			if (a->elem[0].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in switch() type %d\n",
						a->elem[0].type);
				ret=E_BUG;
				break;
			}
			spec = (pv_spec_t*)a->elem[0].u.data;
			if(pv_get_spec_value(msg, spec, &val)!=0)
			{
				LM_ALERT("BUG - no value in switch()\n");
				ret=E_BUG;
				break;
			}

			/* get the value of pvar */
			if(a->elem[1].type!=ACTIONS_ST) {
				LM_ALERT("BUG in switch() actions\n");
				ret=E_BUG;
				break;
			}
			return_code=1;
			adefault = NULL;
			aitem = (struct action*)a->elem[1].u.data;
			cmatch=0;
			while(aitem)
			{
				if((unsigned char)aitem->type==DEFAULT_T)
					adefault=aitem;
				if(cmatch==0)
				{
					if(aitem->elem[0].type==STR_ST)
					{
						if(val.flags&PV_VAL_STR
								&& val.rs.len==aitem->elem[0].u.s.len
								&& strncasecmp(val.rs.s, aitem->elem[0].u.s.s,
									val.rs.len)==0)
							cmatch = 1;
					} else { /* number */
						if(val.flags&PV_VAL_INT && 
								val.ri==aitem->elem[0].u.number)
							cmatch = 1;
					}
				}
				if(cmatch==1)
				{
					if(aitem->elem[1].u.data)
					{
						return_code=run_action_list(
							(struct action*)aitem->elem[1].u.data, msg);
						if ((action_flags&ACT_FL_RETURN) ||
						(action_flags&ACT_FL_EXIT))
							break;
					}
					if(aitem->elem[2].u.number==1)
						break;
				}
				aitem = aitem->next;
			}
			if((cmatch==0) && (adefault!=NULL))
			{
				LM_DBG("switch: running default statement\n");
				if(adefault->elem[0].u.data)
					return_code=run_action_list(
						(struct action*)adefault->elem[0].u.data, msg);
			}
			ret=return_code;
			break;
		case MODULE_T:
			script_trace("module", ((cmd_export_t*)(a->elem[0].u.data))->name,
				msg, a->line) ;
			if ( (a->elem[0].type==CMD_ST) && a->elem[0].u.data ) {
				ret=((cmd_export_t*)(a->elem[0].u.data))->function(msg,
						 (char*)a->elem[1].u.data, (char*)a->elem[2].u.data,
						 (char*)a->elem[3].u.data, (char*)a->elem[4].u.data,
						 (char*)a->elem[5].u.data, (char*)a->elem[6].u.data);
			}else{
				LM_ALERT("BUG in module call\n");
			}
			break;
		case FORCE_RPORT_T:
			script_trace("core", "force_rport", msg, a->line) ;
			msg->msg_flags|=FL_FORCE_RPORT;
			ret=1; /* continue processing */
			break;
		case FORCE_LOCAL_RPORT_T:
			script_trace("core", "force_local_rport", msg, a->line) ;
			msg->msg_flags|=FL_FORCE_LOCAL_RPORT;
			ret=1; /* continue processing */
			break;
		case SET_ADV_ADDR_T:
			script_trace("core", "set_adv_addr", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in set_advertised_address() "
						"type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			str adv_addr;
			pve = (pv_elem_t *)a->elem[0].u.data;
			if ( pv_printf_s(msg, pve, &adv_addr)!=0 || 
			adv_addr.len == 0 || adv_addr.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}
			LM_DBG("adv address = [%.*s]\n",adv_addr.len,adv_addr.s);
			msg->set_global_address=adv_addr;
			ret=1; /* continue processing */
			break;
		case SET_ADV_PORT_T:
			script_trace("core", "set_adv_port", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in set_advertised_port() "
						"type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}

			msg->set_global_port=*((str*)a->elem[0].u.data);
			ret=1; /* continue processing */
			break;
#ifdef USE_TCP
		case FORCE_TCP_ALIAS_T:
			script_trace("core", "force_tcp_alias", msg, a->line) ;
			if ( msg->rcv.proto==PROTO_TCP
#ifdef USE_TLS
					|| msg->rcv.proto==PROTO_TLS
#endif
			   ){
				
				if (a->elem[0].type==NOSUBTYPE)	port=msg->via1->port;
				else if (a->elem[0].type==NUMBER_ST)
					port=(int)a->elem[0].u.number;
				else{
					LM_ALERT("BUG in force_tcp_alias"
							" port type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
						
				if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
									msg->rcv.proto)!=0){
					LM_ERR("tcp alias failed\n");
					ret=E_UNSPEC;
					break;
				}
			}
#endif
			ret=1; /* continue processing */
			break;
		case FORCE_SEND_SOCKET_T:
			script_trace("core", "force_send_socket", msg, a->line) ;
			if (a->elem[0].type!=SOCKETINFO_ST){
				LM_ALERT("BUG in force_send_socket argument"
						" type: %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			msg->force_send_socket=(struct socket_info*)a->elem[0].u.data;
			ret=1; /* continue processing */
			break;
		case SERIALIZE_BRANCHES_T:
			script_trace("core", "serialize_branches", msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST){
				LM_ALERT("BUG in serialize_branches argument"
						" type: %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if (serialize_branches(msg,(int)a->elem[0].u.number)!=0) {
				LM_ERR("serialize_branches failed\n");
				ret=E_UNSPEC;
				break;
			}
			ret=1; /* continue processing */
			break;
		case NEXT_BRANCHES_T:
			script_trace("core", "next_branches", msg, a->line) ;
			if ((ret=next_branches(msg))<0) {
				LM_ERR("next_branches failed\n");
				ret=E_UNSPEC;
				break;
			}
			/* continue processing */
			break;
		case EQ_T:
		case COLONEQ_T:
		case PLUSEQ_T:
		case MINUSEQ_T:
		case DIVEQ_T:
		case MULTEQ_T:
		case MODULOEQ_T:
		case BANDEQ_T:
		case BOREQ_T:
		case BXOREQ_T:
			ret = do_assign(msg, a);
			break;
		case USE_BLACKLIST_T:
			script_trace("core", "use_blacklist", msg, a->line) ;
			mark_for_search((struct bl_head*)a->elem[0].u.data, 1);
			break;
		case UNUSE_BLACKLIST_T:
			script_trace("core", "unuse_blacklist", msg, a->line);
			mark_for_search((struct bl_head*)a->elem[0].u.data, 0);
			break;
		case PV_PRINTF_T:
			script_trace("core", "pv_printf", msg, a->line);
			ret = -1;
			spec = (pv_spec_p)a->elem[0].u.data;
			if(!pv_is_w(spec))
			{
				LM_ERR("read only PV in first parameter of pv_printf\n");
				goto error;
			}

			model = (pv_elem_p)a->elem[1].u.data;

			memset(&val, 0, sizeof(pv_value_t));
			if(pv_printf_s(msg, model, &val.rs)!=0)
			{
				LM_ERR("cannot eval second parameter\n");
				goto error;
			}
			val.flags = PV_VAL_STR;
			if(pv_set_value(msg, spec, EQ_T, &val)<0)
			{
				LM_ERR("setting PV failed\n");
				goto error;
			}
			
			ret = 1;
			break;
		case SCRIPT_TRACE_T:
			script_trace("core", "script_trace", msg, a->line);
			if (a->elem[0].type==NOSUBTYPE) {
				use_script_trace = 0;
			} else {
				
				use_script_trace = 1;
				
				if (a->elem[0].type != NUMBER_ST ||
					a->elem[1].type != SCRIPTVAR_ELEM_ST) {

					LM_ERR("BUG in use_script_trace() arguments\n");
					ret=E_BUG;
					break;
				}

				if (a->elem[2].type!=NOSUBTYPE) {
					script_trace_info = (char *)a->elem[2].u.data;
				} else {
					script_trace_info = NULL;
				}

				script_trace_log_level = (int)a->elem[0].u.number;
				script_trace_elem = *(pv_elem_p)a->elem[1].u.data;
			}

			break;
		default:
			LM_ALERT("BUG - unknown type %d\n", a->type);
			goto error;
	}

	if((unsigned char)a->type!=IF_T && (unsigned char)a->type!=ROUTE_T)
		return_code = ret;
/*skip:*/

	update_longest_action();
	return ret;

error:
	LM_ERR("error at line: %d\n", a->line);
	update_longest_action();
	return ret;
	
error_uri:
	LM_ERR("set*: uri too long\n");
	if (new_uri) pkg_free(new_uri);
	update_longest_action();
	return E_UNSPEC;
error_fwd_uri:
	update_longest_action();
	return ret;
}
Ejemplo n.º 16
0
/* Callback function that is passed to pcap_loop() */
void callback_proto(u_char *useless, struct pcap_pkthdr *pkthdr, u_char *packet) {

	uint8_t hdr_offset = 0;

	uint8_t erspan_offset = 0;
	uint8_t tmp_ip_proto = 0;
	uint8_t tmp_ip_len = 0;

	uint16_t ethaddr;
	uint16_t mplsaddr;

	uint8_t loc_index = (uint8_t) *useless;

	if (profile_socket[loc_index].erspan == 1) {
		memcpy(&tmp_ip_proto, (packet + ETHHDR_SIZE + IPPROTO_OFFSET), 1);
		if (tmp_ip_proto == GRE_PROTO) {
			memcpy(&tmp_ip_len, (packet + ETHHDR_SIZE), 1);
			tmp_ip_len = (tmp_ip_len & IPLEN_MASK) * 4; // LSB 4 bits: length in 32-bit words
			//printf("ip.proto: %d, ip header len: %d\n", tmp_ip_proto, tmp_ip_len);
			erspan_offset = ETHHDR_SIZE + tmp_ip_len + GREHDR_SIZE; // Ethernet + IP + GRE
			pkthdr->len -= erspan_offset;
			pkthdr->caplen -= erspan_offset;
			packet += erspan_offset;
		}
	}

	/* Pat Callahan's patch for MPLS */
	memcpy(&ethaddr, (packet + 12), 2);
        memcpy(&mplsaddr, (packet + 16), 2);

        if (ntohs(ethaddr) == 0x8100) {
          if (ntohs(mplsaddr) == 0x8847) {
             hdr_offset = 8;
          } else {
             hdr_offset = 4;
          }
        }

        struct ether_header *eth = (struct ether_header *)packet;
        struct run_act_ctx ctx;                
        
        struct ip      *ip4_pkt = (struct ip *)    (packet + link_offset + hdr_offset);
#if USE_IPv6
        struct ip6_hdr *ip6_pkt = (struct ip6_hdr*)(packet + link_offset + hdr_offset);
#endif

	msg_t _msg;
	uint32_t ip_ver;
	uint8_t ip_proto = 0;
	uint32_t ip_hl = 0;
	uint32_t ip_off = 0;
	uint8_t fragmented = 0;
	uint16_t frag_offset = 0;
	//uint32_t frag_id = 0;
	char ip_src[INET6_ADDRSTRLEN + 1], ip_dst[INET6_ADDRSTRLEN + 1];
	char mac_src[20], mac_dst[20];
	u_char *pack = NULL;
	unsigned char *data, *datatcp;	        
	int action_idx = 0;	
	uint32_t len = pkthdr->caplen;
	uint8_t  psh = 0;
	        
	/* stats */
	stats.received_packets_total++;

	if (profile_socket[loc_index].reasm == 1 && reasm[loc_index] != NULL) {
		unsigned new_len;

		u_char *new_p = malloc(len - link_offset - hdr_offset);
		memcpy(new_p, ip4_pkt, len - link_offset - hdr_offset);

		pack = reasm_ip_next(reasm[loc_index], new_p, len - link_offset - hdr_offset,
				(reasm_time_t) 1000000UL * pkthdr->ts.tv_sec + pkthdr->ts.tv_usec, &new_len);

		if (pack == NULL) return;

		len = new_len + link_offset + hdr_offset;
		pkthdr->len = new_len;
		pkthdr->caplen = new_len;

		ip4_pkt = (struct ip *) pack;
#if USE_IPv6
		ip6_pkt = (struct ip6_hdr*)pack;
#endif
	}

	ip_ver = ip4_pkt->ip_v;

		//BSD
        snprintf(mac_src, sizeof(mac_src), "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",eth->ether_shost[0] , eth->ether_shost[1] , eth->ether_shost[2] , eth->ether_shost[3] , eth->ether_shost[4] , eth->ether_shost[5]);
        snprintf(mac_dst, sizeof(mac_dst), "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",eth->ether_dhost[0] , eth->ether_dhost[1] , eth->ether_dhost[2] , eth->ether_dhost[3] , eth->ether_dhost[4] , eth->ether_dhost[5]);
        
        memset(&_msg, 0, sizeof(msg_t));
        memset(&ctx, 0, sizeof(struct run_act_ctx));
        
        _msg.cap_packet = (void *) packet;
        _msg.cap_header = (void *) pkthdr;                

	switch (ip_ver) {

	case 4: {
#if defined(AIX)
#undef ip_hl
		ip_hl = ip4_pkt->ip_ff.ip_fhl * 4;
#else
		ip_hl = ip4_pkt->ip_hl * 4;
#endif
		ip_proto = ip4_pkt->ip_p;
		ip_off = ntohs(ip4_pkt->ip_off);

		fragmented = ip_off & (IP_MF | IP_OFFMASK);
		frag_offset = (fragmented) ? (ip_off & IP_OFFMASK) * 8 : 0;
		//frag_id = ntohs(ip4_pkt->ip_id);

		inet_ntop(AF_INET, (const void *) &ip4_pkt->ip_src, ip_src, sizeof(ip_src));
		inet_ntop(AF_INET, (const void *) &ip4_pkt->ip_dst, ip_dst, sizeof(ip_dst));
	}
		break;

#if USE_IPv6
		case 6: {
			ip_hl = sizeof(struct ip6_hdr);
			ip_proto = ip6_pkt->ip6_nxt;

			if (ip_proto == IPPROTO_FRAGMENT) {
				struct ip6_frag *ip6_fraghdr;

				ip6_fraghdr = (struct ip6_frag *)((unsigned char *)(ip6_pkt) + ip_hl);
				ip_hl += sizeof(struct ip6_frag);
				ip_proto = ip6_fraghdr->ip6f_nxt;

				fragmented = 1;
				frag_offset = ntohs(ip6_fraghdr->ip6f_offlg & IP6F_OFF_MASK);
				//frag_id = ntohl(ip6_fraghdr->ip6f_ident);
			}

			inet_ntop(AF_INET6, (const void *)&ip6_pkt->ip6_src, ip_src, sizeof(ip_src));
			inet_ntop(AF_INET6, (const void *)&ip6_pkt->ip6_dst, ip_dst, sizeof(ip_dst));
		}break;
#endif
	}

	switch (ip_proto) {
	case IPPROTO_TCP: {
		struct tcphdr *tcp_pkt = (struct tcphdr *) ((unsigned char *) (ip4_pkt) + ip_hl);

		//uint16_t tcphdr_offset = (frag_offset) ? 0 : (tcp_pkt->th_off * 4);
		uint16_t tcphdr_offset = frag_offset ? 0 : (uint16_t) (tcp_pkt->th_off * 4);

		data = (unsigned char *) tcp_pkt + tcphdr_offset;
		
		_msg.hdr_len = link_offset + hdr_offset + ip_hl + tcphdr_offset;
		
		len -= link_offset + hdr_offset + ip_hl + tcphdr_offset;

		stats.received_tcp_packets++;

#if USE_IPv6
		/* if (ip_ver == 6)
		{
        		len -= ntohs(ip6_pkt->ip6_plen);
        		_msg.hdr_len += ntohs(ip6_pkt->ip6_plen);
                }
                */
#endif



		if ((int32_t) len < 0) len = 0;

		if(tcpreasm[loc_index] != NULL &&  (len > 0) && (tcp_pkt->th_flags & TH_ACK)) {

                        unsigned new_len;
                        u_char *new_p_2 = malloc(len+10);
                        memcpy(new_p_2, data, len);
        
                        if((tcp_pkt->th_flags & TH_PUSH)) psh = 1;

                                        
                        if(debug_socket_pcap_enable) LDEBUG("DEFRAG TCP process: LEN:[%d], ACK:[%d], PSH[%d]\n", len, (tcp_pkt->th_flags & TH_ACK), psh);
                        
                        datatcp = tcpreasm_ip_next_tcp(tcpreasm[loc_index], new_p_2, len , (tcpreasm_time_t) 1000000UL * pkthdr->ts.tv_sec + pkthdr->ts.tv_usec, &new_len, &ip4_pkt->ip_src, &ip4_pkt->ip_dst, ntohs(tcp_pkt->th_sport), ntohs(tcp_pkt->th_dport), psh);

                        if (datatcp == NULL) return;
                                                
                        len = new_len;
                        
                        if(debug_socket_pcap_enable)
                                LDEBUG("COMPLETE TCP DEFRAG: LEN[%d], PACKET:[%s]\n", len, datatcp);
                        

			if(!profile_socket[profile_size].full_packet) {
		        	_msg.data = datatcp;
	        		_msg.len = len;
        	        }
			else {
			       // _msg.len = pkthdr->caplen - link_offset;
			       // _msg.data = (packet + link_offset);
			       _msg.data = datatcp;
	        		_msg.len = len;		        
                	}

			_msg.rcinfo.src_port = ntohs(tcp_pkt->th_sport);
			_msg.rcinfo.dst_port = ntohs(tcp_pkt->th_dport);
			_msg.rcinfo.src_ip = ip_src;
			_msg.rcinfo.dst_ip = ip_dst;
			_msg.rcinfo.src_mac = mac_src;
			_msg.rcinfo.dst_mac = mac_dst;
			_msg.rcinfo.ip_family = ip_ver == 4 ? AF_INET : AF_INET6;
			_msg.rcinfo.ip_proto = ip_proto;
			_msg.rcinfo.time_sec = pkthdr->ts.tv_sec;
			_msg.rcinfo.time_usec = pkthdr->ts.tv_usec;
			_msg.tcpflag = tcp_pkt->th_flags;
			_msg.parse_it = 1;

			action_idx = profile_socket[loc_index].action;		
			run_actions(&ctx, main_ct.clist[action_idx], &_msg);
			
			/**
			   hook to function process_packet:
			   in process_packet I have to prepare the Key
			   and the Handshake for Hashtable 
			*/
			
                        /* clear datatcp */
                        free(datatcp);                    
		}
		else {

			if(!profile_socket[profile_size].full_packet) {
			        _msg.data = data;
        			_msg.len = len;
        	        }
			else {
			        _msg.len = pkthdr->caplen - link_offset - hdr_offset;
			        _msg.data = (packet + link_offset + hdr_offset);
        	        }

			_msg.rcinfo.src_port = ntohs(tcp_pkt->th_sport);
			_msg.rcinfo.dst_port = ntohs(tcp_pkt->th_dport);
			_msg.rcinfo.src_ip = ip_src;
			_msg.rcinfo.dst_ip = ip_dst;
			_msg.rcinfo.src_mac = mac_src;
			_msg.rcinfo.dst_mac = mac_dst;
			_msg.rcinfo.ip_family = ip_ver == 4 ? AF_INET : AF_INET6;
			_msg.rcinfo.ip_proto = ip_proto;
			_msg.rcinfo.time_sec = pkthdr->ts.tv_sec;
			_msg.rcinfo.time_usec = pkthdr->ts.tv_usec;
			_msg.tcpflag = tcp_pkt->th_flags;
			_msg.parse_it = 1;

			action_idx = profile_socket[loc_index].action;		
			run_actions(&ctx, main_ct.clist[action_idx], &_msg);
		        
			stats.send_packets++;

                }

	}
		break;

	case IPPROTO_UDP: {
		struct udphdr *udp_pkt = (struct udphdr *) ((unsigned char *) (ip4_pkt) + ip_hl);
		uint16_t udphdr_offset = (frag_offset) ? 0 : sizeof(*udp_pkt);

		data = (unsigned char *) (udp_pkt) + udphdr_offset;
		
		_msg.hdr_len = link_offset + ip_hl + hdr_offset + udphdr_offset;
		
		len -= link_offset + ip_hl + udphdr_offset + hdr_offset;
		
		
#if USE_IPv6
		/*if (ip_ver == 6) {
        		len -= ntohs(ip6_pkt->ip6_plen);
        		_msg.hdr_len += ntohs(ip6_pkt->ip6_plen);
                }
                */		
#endif

		/* stats */
		stats.received_udp_packets++;

		if ((int32_t) len < 0) len = 0;

		if(!profile_socket[profile_size].full_packet) {
		        _msg.data = data;
        		_msg.len = len;
                }
		else {
		        _msg.len = pkthdr->caplen - link_offset - hdr_offset;
		        _msg.data = (packet + link_offset + hdr_offset);
		        
                }		                                                                                                                                                  		

	
		_msg.rcinfo.src_port = ntohs(udp_pkt->uh_sport);
		_msg.rcinfo.dst_port = ntohs(udp_pkt->uh_dport);
		_msg.rcinfo.src_ip = ip_src;
		_msg.rcinfo.dst_ip = ip_dst;
		_msg.rcinfo.src_mac = mac_src;
		_msg.rcinfo.dst_mac = mac_dst;
		_msg.rcinfo.ip_family = ip_ver == 4 ? AF_INET : AF_INET6;
		_msg.rcinfo.ip_proto = ip_proto;
		_msg.rcinfo.time_sec = pkthdr->ts.tv_sec;
		_msg.rcinfo.time_usec = pkthdr->ts.tv_usec;
		_msg.tcpflag = 0;
		_msg.parse_it = 1;


		action_idx = profile_socket[loc_index].action;
		run_actions(&ctx, main_ct.clist[action_idx], &_msg);


		stats.send_packets++;

	}
		break;

	case IPPROTO_SCTP: {
		struct sctp_common_hdr *sctp_hdr;
		uint8_t *chunk_data;
		int plen;
		uint32_t chunk_read = 0;

		/* attempt at input validation */
		if (len <= link_offset + ip_hl + hdr_offset) {
			LDEBUG("sctp: offset handling %zu vs. %zu",
				len, link_offset + ip_hl + hdr_offset);
			goto error;
		}

		len -= link_offset + ip_hl + hdr_offset;
		sctp_hdr = (struct sctp_common_hdr *) ((uint8_t *)(ip4_pkt) + ip_hl);
		plen = sctp_parse_common(&_msg, (uint8_t *)sctp_hdr, len);

		if (plen < 0)
			goto error;
		len -= plen;

		/* stats */
		stats.received_sctp_packets++;

		/* I don't understand the frag_offset in other protos */

		/* same for the entire package */
		_msg.hdr_len = link_offset + hdr_offset + ip_hl + sizeof(struct sctp_common_hdr);
		_msg.rcinfo.src_ip = ip_src;
		_msg.rcinfo.dst_ip = ip_dst;
		_msg.rcinfo.src_mac = mac_src;
		_msg.rcinfo.dst_mac = mac_dst;
		_msg.rcinfo.ip_family = ip_ver == 4 ? AF_INET : AF_INET6;
		_msg.rcinfo.ip_proto = ip_proto;
		_msg.rcinfo.time_sec = pkthdr->ts.tv_sec;
		_msg.rcinfo.time_usec = pkthdr->ts.tv_usec;
		_msg.tcpflag = 0;
		_msg.parse_it = 1;


		/* default the full packet */
	        _msg.len = pkthdr->caplen - link_offset - hdr_offset;
	        _msg.data = (packet + link_offset + hdr_offset);

		chunk_data = &sctp_hdr->data[0];

		while (chunk_read < len) {
			bool send_data;
			uint8_t padding;

			plen = sctp_parse_chunk(&_msg, chunk_data, len - chunk_read, &send_data);
			if (plen < 0)
				goto error;
			/* a chunk but no data chunk */
			if (!send_data)
				goto next;

			if (!profile_socket[profile_size].full_packet) {
				_msg.len = plen - 16;
				_msg.data = chunk_data + 16;
			}
			action_idx = profile_socket[loc_index].action;
			run_actions(&ctx, main_ct.clist[action_idx], &_msg);

next:
			padding = (4 - (plen % 4)) & 0x3;
			chunk_read += plen + padding;
			chunk_data += plen + padding;
		}

		stats.send_packets++;
	}
		break;

	default:
		break;
	}

error:
	if(pack != NULL) free(pack);
}
Ejemplo n.º 17
0
void async_cdp_uar_callback(int is_timeout, void *param, AAAMessage *uaa, long elapsed_msecs) {
    struct run_act_ctx ra_ctx;
    str server_name;
    int *m_capab = 0, m_capab_cnt = 0;
    int *o_capab = 0, o_capab_cnt = 0;
    str *p_server_names = 0;
    int p_server_names_cnt = 0;
    int rc = -1, experimental_rc = -1;
    saved_uar_transaction_t* data = (saved_uar_transaction_t*) param;
    struct cell *t = 0;
    int result = CSCF_RETURN_TRUE;
    scscf_entry *list = 0;

    if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
        LM_ERR("ERROR: t_continue: transaction not found\n");
        //result = CSCF_RETURN_ERROR;//not needed we set by default to error!
        goto error;
    }

    if (is_timeout != 0) {
        LM_ERR("Error timeout when  sending message via CDP\n");
        update_stat(stat_uar_timeouts, 1);
        goto error;
    }

    //update stats on response time
    update_stat(uar_replies_received, 1);
    update_stat(uar_replies_response_time, elapsed_msecs);

    if (!uaa) {
        LM_ERR("Error sending message via CDP\n");
        //result = CSCF_RETURN_ERROR;//not needed we set by default to error!
        goto error;
    }

    server_name = cxdx_get_server_name(uaa);
    if (!server_name.len) {
        cxdx_get_capabilities(uaa, &m_capab, &m_capab_cnt, &o_capab,
                &o_capab_cnt, &p_server_names, &p_server_names_cnt);
    }

    cxdx_get_result_code(uaa, &rc);
    cxdx_get_experimental_result_code(uaa, &experimental_rc);

    if (rc && !experimental_rc) {
        LM_ERR("No result code or experimental result code - responding 480\n");
        cscf_reply_transactional_async(t, t->uas.request, 480, MSG_480_DIAMETER_MISSING_AVP);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    switch (rc) {
        case -1:
            switch (experimental_rc) {
                case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN:
                    /* Check, if route is set: */
                    if (route_uar_user_unknown_no >= 0) {
                        /* exec routing script */
                        init_run_actions_ctx(&ra_ctx);
                        if (run_actions(&ra_ctx, main_rt.rlist[route_uar_user_unknown_no], t->uas.request) < 0) {
                            LM_DBG("ims_icscf: error while trying script\n");
                        }
                    } else {
                        cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_USER_UNKNOWN);
                    }
                    LM_ERR("RC_IMS_DIAMETER_ERROR_USER_UNKNOWN\n");
                    result = CSCF_RETURN_FALSE;
                    goto done;
                case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH:
                    LM_ERR("RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH returning 403\n");
                    cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_IDENTITIES_DONT_MATCH);
                    result = CSCF_RETURN_FALSE;
                    goto done;
                case RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED:
                    LM_ERR("RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED returning 403\n");
                    cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_ROAMING_NOT_ALLOWED);
                    result = CSCF_RETURN_FALSE;
                    goto done;
                case RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED:
                    LM_ERR("RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED returning 403\n");
                    cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_IDENTITY_NOT_REGISTERED);
                    result = CSCF_RETURN_FALSE;
                    goto done;
                case RC_IMS_DIAMETER_FIRST_REGISTRATION:
                    goto success;
                case RC_IMS_DIAMETER_SUBSEQUENT_REGISTRATION:
                    goto success;
                case RC_IMS_DIAMETER_SERVER_SELECTION:
                    goto success;

                default:
                    LM_ERR("MSG_403_UNKOWN_EXPERIMENTAL_RC returning 500\n");
                    cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_UNKOWN_EXPERIMENTAL_RC);
                    result = CSCF_RETURN_FALSE;
                    goto done;
            }
            break;

        case AAA_AUTHORIZATION_REJECTED:
            LM_ERR("AAA_AUTHORIZATION_REJECTED returning 403\n");
            cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_AUTHORIZATION_REJECTED);
            result = CSCF_RETURN_FALSE;
            goto done;
        case AAA_UNABLE_TO_COMPLY:
            LM_ERR("AAA_UNABLE_TO_COMPLY returning 403\n");
            cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_UNABLE_TO_COMPLY);
            result = CSCF_RETURN_FALSE;
            goto done;

        case AAA_SUCCESS:
            goto success;

        default:
            LM_ERR("MSG_403_UNKOWN_RC returning 403\n");
            cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_UNKOWN_RC);
            result = CSCF_RETURN_FALSE;
            goto done;
    }

success:
    LM_DBG("successful UAA response\n");
    list = I_get_capab_ordered(server_name, m_capab, m_capab_cnt, o_capab, o_capab_cnt, p_server_names, p_server_names_cnt, 0);

    if (!list) {
        LM_ERR("Empty capability list returning 600\n");
        cscf_reply_transactional_async(t, t->uas.request, 600, MSG_600_EMPTY_LIST);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    if (!data->callid.len || !add_scscf_list(data->callid, list)) {
        LM_ERR("Error saving capability list 500\n");
        cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_ERROR_SAVING_LIST);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    result = CSCF_RETURN_TRUE;

done:
	//free capabilities if they exist
	if (m_capab) shm_free(m_capab);
	if (o_capab) shm_free(o_capab);
	if (p_server_names) shm_free(p_server_names);

    LM_DBG("DBG:UAR Async CDP callback: ... Done resuming transaction\n");
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    create_uaa_return_code(result);

    if (t)tmb.unref_cell(t);
    //free memory
    if (uaa) cdpb.AAAFreeMessage(&uaa);

    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_uar_transaction_data(data);
    return;

error:
    if (t)tmb.unref_cell(t);
    //free memory
    if (uaa) cdpb.AAAFreeMessage(&uaa);

    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_uar_transaction_data(data);


}
Ejemplo n.º 18
0
void on_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* rcvbuf, const struct sockaddr* addr, unsigned flags) 
#endif    
{
       
    msg_t _msg;
    struct timeval  tv;
    int action_idx = 0;
    struct run_act_ctx ctx;
    struct sockaddr_in *cliaddr;
    uint8_t loc_idx;

    if (nread <= 0 || addr == NULL) 
    {
#if UV_VERSION_MAJOR == 0                            
    	free(rcvbuf.base);
#else
        free(rcvbuf->base);
#endif       	
    	return;
    }

    loc_idx = *((uint8_t *) handle->data);
    
    gettimeofday(&tv, NULL);

    cliaddr = (struct sockaddr_in*)addr;

    memset(&_msg, 0, sizeof(msg_t));
    memset(&ctx, 0, sizeof(struct run_act_ctx));

#if UV_VERSION_MAJOR == 0                             
    _msg.data = rcvbuf.base;
#else
    _msg.data = rcvbuf->base;
#endif    

    _msg.len = nread;
    
    _msg.rcinfo.dst_port = ntohs(cliaddr->sin_port);
    _msg.rcinfo.dst_ip = inet_ntoa(cliaddr->sin_addr);
    _msg.rcinfo.liid = loc_idx;

    _msg.rcinfo.src_port = atoi(profile_socket[loc_idx].port);
    _msg.rcinfo.src_ip = profile_socket[loc_idx].host;

    _msg.rcinfo.ip_family = addr->sa_family;
    _msg.rcinfo.ip_proto = IPPROTO_UDP;
		
    _msg.rcinfo.proto_type = profile_socket[loc_idx].protocol;
    _msg.rcinfo.time_sec = tv.tv_sec;
    _msg.rcinfo.time_usec = tv.tv_usec;
    _msg.tcpflag = 0;
    _msg.parse_it = 0;
    _msg.rcinfo.socket = &profile_socket[loc_idx].socket;

    _msg.var = (void *) addr;
    _msg.flag[5] = loc_idx;

    if(nread > 150)
    {
            action_idx = profile_socket[loc_idx].action;
            run_actions(&ctx, main_ct.clist[action_idx], &_msg);		                        
    }
    
#if UV_VERSION_MAJOR == 0                            
    	free(rcvbuf.base);
#else
        free(rcvbuf->base);
#endif       	
}
Ejemplo n.º 19
0
static ticks_t timer_handler(ticks_t ticks, struct timer_ln* tl, void* data) {
	/*?min length of first line of message is 16 char!?*/
	#define MSG "GET /timer HTTP/0.9\n\n"
	struct sip_msg* msg;
	struct timer_action *a;
	struct run_act_ctx ra_ctx;

	a = data;
	if (!a->disable_itself) {

		DEBUG(MODULE_NAME": handler: called at %d ticks, timer: '%s', pid:%d\n", ticks, a->timer_name, getpid());

		if (a->route_no >= main_rt.idx) {
			BUG(MODULE_NAME": invalid routing table number #%d of %d\n", a->route_no, main_rt.idx);
			goto err2;
		}
		if (!main_rt.rlist[a->route_no]) {
			WARN(MODULE_NAME": route not declared (hash:%d)\n", a->route_no);
			goto err2;
		}
		msg=pkg_malloc(sizeof(struct sip_msg));
		if (msg==0) {
			ERR(MODULE_NAME": handler: no mem for sip_msg\n");
			goto err2;
		}
		timer_msg_no++;
		memset(msg, 0, sizeof(struct sip_msg)); /* init everything to 0 */

		msg->buf=MSG;
		msg->len=sizeof(MSG)-1;

		msg->rcv= rcv_info;
		msg->id=timer_msg_no;
		msg->set_global_address=default_global_address;
		msg->set_global_port=default_global_port;

		if (parse_msg(msg->buf, msg->len, msg)!=0){
			ERR(MODULE_NAME": handler: parse_msg failed\n");
			goto err;
		}
		/* ... clear branches from previous message */
		clear_branches();
		reset_static_buffer();
		if (exec_pre_req_cb(msg)==0 )
			goto end; /* drop the request */
		/* exec the routing script */
		timer_executed = a;
		init_run_actions_ctx(&ra_ctx);
		run_actions(&ra_ctx, main_rt.rlist[a->route_no], msg);
		timer_executed = 0;
		/* execute post request-script callbacks */
		exec_post_req_cb(msg);
	end:
		reset_avps();
		DEBUG(MODULE_NAME": handler: cleaning up\n");
	err:
		free_sip_msg(msg);
		pkg_free(msg);
	err2:	;
	}
        /* begin critical section */
	if (a->disable_itself) {

		timer_allow_del(a->link);
		timer_del(a->link);
		timer_reinit(a->link);
		a->disable_itself = 0;
	        /* end critical section */
		return 0;   /* do no call more */
	}
	else
        	return (ticks_t)(-1); /* periodical */
}
Ejemplo n.º 20
0
/* ret= 0! if action -> end of list(e.g DROP), 
      > 0 to continue processing next actions
   and <0 on error */
int do_action(struct action* a, struct sip_msg* msg)
{
	int ret;
	int v;
	union sockaddr_union* to;
	struct socket_info* send_sock;
	struct proxy_l* p;
	char* tmp;
	char *new_uri, *end, *crt;
	int len;
	int user;
	struct sip_uri uri, next_hop;
	struct sip_uri* u;
	unsigned short port;
	int proto;

	/* reset the value of error to E_UNSPEC so avoid unknowledgable
	   functions to return with errror (status<0) and not setting it
	   leaving there previous error; cache the previous value though
	   for functions which want to process it */
	prev_ser_error=ser_error;
	ser_error=E_UNSPEC;

	ret=E_BUG;
	switch ((unsigned char)a->type){
		case DROP_T:
				ret=0;
			break;
		case FORWARD_T:
#ifdef USE_TCP
		case FORWARD_TCP_T:
#endif
#ifdef USE_TLS
		case FORWARD_TLS_T:
#endif
		case FORWARD_UDP_T:

			if (a->type==FORWARD_UDP_T) proto=PROTO_UDP;
#ifdef USE_TCP
			else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP;
#endif
#ifdef USE_TLS
			else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS;
#endif
			else proto=msg->rcv.proto;
			if (a->p1_type==URIHOST_ST){
				/*parse uri*/

				if (msg->dst_uri.len) {
					ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop);
					u = &next_hop;
				} else {
					ret = parse_sip_msg_uri(msg);
					u = &msg->parsed_uri;
				}

				if (ret<0) {
					LOG(L_ERR, "ERROR: do_action: forward: bad_uri "
								" dropping packet\n");
					break;
				}
				
				switch (a->p2_type){
					case URIPORT_ST:
									port=u->port_no;
									break;
					case NUMBER_ST:
									port=a->p2.number;
									break;
					default:
							LOG(L_CRIT, "BUG: do_action bad forward 2nd"
										" param type (%d)\n", a->p2_type);
							ret=E_UNSPEC;
							goto error_fwd_uri;
				}
				switch(u->proto){
					case PROTO_NONE:
						proto=PROTO_UDP;
						break;
					case PROTO_UDP:
#ifdef USE_TCP
					case PROTO_TCP:
#endif
#ifdef USE_TLS
					case PROTO_TLS:
#endif
						proto=u->proto;
						break;
					default:
						LOG(L_ERR,"ERROR: do action: forward: bad uri"
								" transport %d\n", u->proto);
						ret=E_BAD_PROTO;
						goto error_fwd_uri;
				}
#ifdef USE_TLS
				if (u->secure){
					if (u->proto==PROTO_UDP){
						LOG(L_ERR, "ERROR: do_action: forward: secure uri"
								" incompatible with transport %d\n", u->proto);
						ret=E_BAD_PROTO;
						goto error_fwd_uri;
					}
					proto=PROTO_TLS;
				}
#endif
				/* create a temporary proxy*/
				p=mk_proxy(&u->host, port, proto);
				if (p==0){
					LOG(L_ERR, "ERROR:  bad host name in uri,"
							" dropping packet\n");
					ret=E_BAD_ADDRESS;
					goto error_fwd_uri;
				}
				ret=forward_request(msg, p, proto);
				/*free_uri(&uri); -- no longer needed, in sip_msg*/
				free_proxy(p); /* frees only p content, not p itself */
				pkg_free(p);
				if (ret>=0) ret=1;
			}else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
				ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto);
				if (ret>=0) ret=1;
			}else{
				LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
						a->p1_type, a->p2_type);
				ret=E_BUG;
			}
			break;
		case SEND_T:
		case SEND_TCP_T:
			if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
				LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
						a->p1_type, a->p2_type);
				ret=E_BUG;
				break;
			}
			to=(union sockaddr_union*)
					pkg_malloc(sizeof(union sockaddr_union));
			if (to==0){
				LOG(L_ERR, "ERROR: do_action: "
							"memory allocation failure\n");
				ret=E_OUT_OF_MEM;
				break;
			}
			
			p=(struct proxy_l*)a->p1.data;
			
			if (p->ok==0){
				if (p->host.h_addr_list[p->addr_idx+1])
					p->addr_idx++;
				else 
					p->addr_idx=0;
				p->ok=1;
			}
			ret=hostent2su(	to, &p->host, p->addr_idx,
						(p->port)?p->port:SIP_PORT );
			if (ret==0){
				p->tx++;
				p->tx_bytes+=msg->len;
				if (a->type==SEND_T){
					/*udp*/
					send_sock=get_send_socket(to, PROTO_UDP);
					if (send_sock!=0){
						ret=udp_send(send_sock, msg->buf, msg->len, to);
					}else{
						ret=-1;
					}
				}
#ifdef USE_TCP
					else{
					/*tcp*/
					ret=tcp_send(PROTO_TCP, msg->buf, msg->len, to, 0);
				}
#endif
			}
			pkg_free(to);
			if (ret<0){
				p->errors++;
				p->ok=0;
			}else ret=1;
			
			break;
		case LOG_T:
			if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){
				LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
						a->p1_type, a->p2_type);
				ret=E_BUG;
				break;
			}
			LOG(a->p1.number, a->p2.string);
			ret=1;
			break;

		/* jku -- introduce a new branch */
		case APPEND_BRANCH_T:
			if ((a->p1_type!=STRING_ST)) {
				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			ret=append_branch( msg, a->p1.string, 
				a->p1.string ? strlen(a->p1.string):0 );
			break;

		/* jku begin: is_length_greater_than */
		case LEN_GT_T:
			if (a->p1_type!=NUMBER_ST) {
				LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			/* DBG("XXX: message length %d, max %d\n", 
				msg->len, a->p1.number ); */
			ret = msg->len >= a->p1.number ? 1 : -1;
			break;
		/* jku end: is_length_greater_than */
			
		/* jku - begin : flag processing */

		case SETFLAG_T:
			if (a->p1_type!=NUMBER_ST) {
				LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			if (!flag_in_range( a->p1.number )) {
				ret=E_CFG;
				break;
			}
			setflag( msg, a->p1.number );
			ret=1;
			break;

		case RESETFLAG_T:
			if (a->p1_type!=NUMBER_ST) {
				LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			if (!flag_in_range( a->p1.number )) {
				ret=E_CFG;
				break;
			}
			resetflag( msg, a->p1.number );
			ret=1;
			break;
			
		case ISFLAGSET_T:
			if (a->p1_type!=NUMBER_ST) {
				LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
					a->p1_type );
				ret=E_BUG;
				break;
			}
			if (!flag_in_range( a->p1.number )) {
				ret=E_CFG;
				break;
			}
			ret=isflagset( msg, a->p1.number );
			break;
		/* jku - end : flag processing */

		case ERROR_T:
			if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){
				LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
						a->p1_type, a->p2_type);
				ret=E_BUG;
				break;
			}
			LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
					"not implemented yet\n", a->p1.string, a->p2.string);
			ret=1;
			break;
		case ROUTE_T:
			if (a->p1_type!=NUMBER_ST){
				LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
						a->p1_type);
				ret=E_BUG;
				break;
			}
			if ((a->p1.number>RT_NO)||(a->p1.number<0)){
				LOG(L_ERR, "ERROR: invalid routing table number in"
							"route(%lu)\n", a->p1.number);
				ret=E_CFG;
				break;
			}
			ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
			break;
		case EXEC_T:
			if (a->p1_type!=STRING_ST){
				LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
						a->p1_type);
				ret=E_BUG;
				break;
			}
			LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
						" using dumb version...\n", a->p1.string);
			ret=system(a->p1.string);
			if (ret!=0){
				LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
			}
			ret=1;
			break;
		case REVERT_URI_T:
			if (msg->new_uri.s) {
				pkg_free(msg->new_uri.s);
				msg->new_uri.len=0;
				msg->new_uri.s=0;
				msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
			};
			ret=1;
			break;
		case SET_HOST_T:
		case SET_HOSTPORT_T:
		case SET_USER_T:
		case SET_USERPASS_T:
		case SET_PORT_T:
		case SET_URI_T:
		case PREFIX_T:
		case STRIP_T:
		case STRIP_TAIL_T:
				user=0;
				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
					if (a->p1_type!=NUMBER_ST) {
						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
							a->p1_type);
						break;
					}
				} else if (a->p1_type!=STRING_ST){
					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
							a->p1_type);
					ret=E_BUG;
					break;
				}
				if (a->type==SET_URI_T){
					if (msg->new_uri.s) {
							pkg_free(msg->new_uri.s);
							msg->new_uri.len=0;
					}
					msg->parsed_uri_ok=0;
					len=strlen(a->p1.string);
					msg->new_uri.s=pkg_malloc(len+1);
					if (msg->new_uri.s==0){
						LOG(L_ERR, "ERROR: do_action: memory allocation"
								" failure\n");
						ret=E_OUT_OF_MEM;
						break;
					}
					memcpy(msg->new_uri.s, a->p1.string, len);
					msg->new_uri.s[len]=0;
					msg->new_uri.len=len;
					
					ret=1;
					break;
				}
				if (msg->new_uri.s) {
					tmp=msg->new_uri.s;
					len=msg->new_uri.len;
				}else{
					tmp=msg->first_line.u.request.uri.s;
					len=msg->first_line.u.request.uri.len;
				}
				if (parse_uri(tmp, len, &uri)<0){
					LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
								" packet\n", tmp);
					ret=E_UNSPEC;
					break;
				}
				
				new_uri=pkg_malloc(MAX_URI_SIZE);
				if (new_uri==0){
					LOG(L_ERR, "ERROR: do_action: memory allocation "
								" failure\n");
					ret=E_OUT_OF_MEM;
					break;
				}
				end=new_uri+MAX_URI_SIZE;
				crt=new_uri;
				/* begin copying */
				len=strlen("sip:"); if(crt+len>end) goto error_uri;
				memcpy(crt,"sip:",len);crt+=len;

				/* user */

				/* prefix (-jiri) */
				if (a->type==PREFIX_T) {
					tmp=a->p1.string;
					len=strlen(tmp); if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
					/* whatever we had before, with prefix we have username 
					   now */
					user=1;
				}

				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
					tmp=a->p1.string;
					len=strlen(tmp);
				} else if (a->type==STRIP_T) {
					if (a->p1.number>uri.user.len) {
						LOG(L_WARN, "Error: too long strip asked; "
									" deleting username: %lu of <%.*s>\n",
									a->p1.number, uri.user.len, uri.user.s );
						len=0;
					} else if (a->p1.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s + a->p1.number;
						len=uri.user.len - a->p1.number;
					}
				} else if (a->type==STRIP_TAIL_T) {
					if (a->p1.number>uri.user.len) {
						LOG(L_WARN, "WARNING: too long strip_tail asked; "
									" deleting username: %lu of <%.*s>\n",
									a->p1.number, uri.user.len, uri.user.s );
						len=0;
					} else if (a->p1.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s;
						len=uri.user.len - a->p1.number;
					}
				} else {
					tmp=uri.user.s;
					len=uri.user.len;
				}

				if (len){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
					user=1; /* we have an user field so mark it */
				}

				if (a->type==SET_USERPASS_T) tmp=0;
				else tmp=uri.passwd.s;
				/* passwd */
				if (tmp){
					len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* host */
				if (user || tmp){ /* add @ */
					if(crt+1>end) goto error_uri;
					*crt='@'; crt++;
				}
				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
					tmp=a->p1.string;
					if (tmp) len = strlen(tmp);
					else len=0;
				} else {
					tmp=uri.host.s;
					len = uri.host.len;
				}
				if (tmp){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* port */
				if (a->type==SET_HOSTPORT_T) tmp=0;
				else if (a->type==SET_PORT_T) {
					tmp=a->p1.string;
					if (tmp) len = strlen(tmp);
					else len = 0;
				} else {
					tmp=uri.port.s;
					len = uri.port.len;
				}
				if (tmp){
					if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* params */
				tmp=uri.params.s;
				if (tmp){
					len=uri.params.len; if(crt+len+1>end) goto error_uri;
					*crt=';'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* headers */
				tmp=uri.headers.s;
				if (tmp){
					len=uri.headers.len; if(crt+len+1>end) goto error_uri;
					*crt='?'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				*crt=0; /* null terminate the thing */
				/* copy it to the msg */
				if (msg->new_uri.s) pkg_free(msg->new_uri.s);
				msg->new_uri.s=new_uri;
				msg->new_uri.len=crt-new_uri;
				msg->parsed_uri_ok=0;
				ret=1;
				break;
		case IF_T:
				/* if null expr => ignore if? */
				if ((a->p1_type==EXPR_ST)&&a->p1.data){
					v=eval_expr((struct expr*)a->p1.data, msg);
					if (v<0){
						if (v==EXPR_DROP){ /* hack to quit on DROP*/
							ret=0;
							break;
						}else{
							LOG(L_WARN,"WARNING: do_action:"
										"error in expression\n");
						}
					}
					
					ret=1;  /*default is continue */
					if (v>0) {
						if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
							ret=run_actions((struct action*)a->p2.data, msg);
						}
					}else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
							ret=run_actions((struct action*)a->p3.data, msg);
					}
				}
			break;
		case MODULE_T:
			if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&
					((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
				ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
													  (char*)a->p3.data);
			}else{
				LOG(L_CRIT,"BUG: do_action: bad module call\n");
			}
			break;
		case FORCE_RPORT_T:
			msg->msg_flags|=FL_FORCE_RPORT;
			ret=1; /* continue processing */
			break;
		case SET_ADV_ADDR_T:
			if (a->p1_type!=STR_ST){
				LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
						"type %d\n", a->p1_type);
				ret=E_BUG;
				break;
			}
			msg->set_global_address=*((str*)a->p1.data);
			ret=1; /* continue processing */
			break;
		case SET_ADV_PORT_T:
			if (a->p1_type!=STR_ST){
				LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
						"type %d\n", a->p1_type);
				ret=E_BUG;
				break;
			}
			msg->set_global_port=*((str*)a->p1.data);
			ret=1; /* continue processing */
			break;
		default:
			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
	}
/*skip:*/
	return ret;
	
error_uri:
	LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
	if (new_uri) pkg_free(new_uri);
	return E_UNSPEC;
error_fwd_uri:
	/*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/
	return ret;
}