示例#1
0
static int lua_sr_resetbflag (lua_State *L)
{
	int flag;
	int branch;
	sr_lua_env_t *env_L;

	env_L = sr_lua_env_get();
	if(lua_gettop(L)==1)
	{
		flag = lua_tointeger(L, -1);
		branch = 0;
	} else if(lua_gettop(L)==2) {
		flag = lua_tointeger(L, -2);
		branch = lua_tointeger(L, -1);
	} else {
		LM_WARN("invalid number of parameters from Lua\n");
		return app_lua_return_false(L);
	}

	if(env_L->msg==NULL)
	{
		LM_WARN("invalid parameters from Lua env\n");
		return app_lua_return_false(L);
	}

	if (!flag_in_range(flag))
	{
		LM_ERR("invalid flag parameter %d\n", flag);
		return app_lua_return_false(L);
	}

	resetbflag(branch, flag);
	return app_lua_return_true(L);
}
示例#2
0
static int lua_sr_isflagset (lua_State *L)
{
	int flag;
	int ret;
	sr_lua_env_t *env_L;

	env_L = sr_lua_env_get();
	flag = lua_tointeger(L, -1);

	if(env_L->msg==NULL)
	{
		LM_WARN("invalid parameters from Lua env\n");
		return app_lua_return_false(L);
	}

	if (!flag_in_range(flag))
	{
		LM_ERR("invalid flag parameter %d\n", flag);
		return app_lua_return_false(L);
	}

	ret = isflagset(env_L->msg, flag);
	if(ret>0)
		return app_lua_return_true(L);
	return app_lua_return_false(L);
}
示例#3
0
/* returns 0 on success, -1 on error */
int check_flag(int n)
{
	if (!flag_in_range(n))
		return -1;
	if (registered_flags[n]){
		LM_WARN("flag %d is already used by a named flag\n", n);
	}
	return 0;
}
示例#4
0
/* returns 0 on success, -1 on error */
int check_flag(int n)
{
	if (!flag_in_range(n))
		return -1;
	if (registered_flags[n]){
		LOG(L_WARN, "WARNING: check_flag: flag %d is already used by "
					" a named flag\n", n);
	}
	return 0;
}
示例#5
0
static int mod_init( void )
{
	if ((pcem_qos_flag != -1) && 
		!flag_in_range(pcem_qos_flag)) {
		LM_ERR("pcem_qos_flag set to invalid value\n");
		return -1;
	}
	if ((pcem_all_flag != -1) && 
		!flag_in_range(pcem_all_flag)) {
		LM_ERR("pcem_all_flag set to invalid value\n");
		return -1;
	}

	/* load the TM API */
	if (load_tm_api(&tmb)!=0) {
		LM_ERR("can't load TM API\n");
		return -1;
	}

	/* load the RR API */
	if (load_rr_api(&rrb)!=0) {
		LM_ERR("can't load RR API\n");
		return -1;
	}
	/* we need the append_fromtag on in RR */
	if (!rrb.append_fromtag) {
		LM_ERR("'append_fromtag' RR param is not enabled\n");
		return -1;
	}

	/* listen for all incoming requests  */
	if ( tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, pcem_onreq, 0, 0 ) <=0 ) {
		LM_ERR("cannot register TMCB_REQUEST_IN callback\n");
		return -1;
	}

	_pcem_module_initialized = 1;

	return 0;
}
示例#6
0
static int mod_init( void )
{
#ifdef SQL_ACC
	if (db_url.s) {
		if(db_url.len<=0) {
			db_url.s = NULL;
			db_url.len = 0;
		}
	}
	if(db_table_acc.len!=3 || strncmp(db_table_acc.s, "acc", 3)!=0)
	{
		db_table_acc_data = db_table_acc.s;
		if(fixup_var_pve_str_12(&db_table_acc_data, 1)<0)
		{
			LM_ERR("unable to parse acc table name [%.*s]\n",
					db_table_acc.len, db_table_acc.s);
			return -1;
		}
	}
	if(db_table_mc.len!=12 || strncmp(db_table_mc.s, "missed_calls", 12)!=0)
	{
		db_table_mc_data = db_table_mc.s;
		if(fixup_var_pve_str_12(&db_table_mc_data, 1)<0)
		{
			LM_ERR("unable to parse mc table name [%.*s]\n",
					db_table_mc.len, db_table_mc.s);
			return -1;
		}
	}
#endif

	if (log_facility_str) {
		int tmp = str2facility(log_facility_str);
		if (tmp != -1)
			log_facility = tmp;
		else {
			LM_ERR("invalid log facility configured");
			return -1;
		}
	}

	/* ----------- GENERIC INIT SECTION  ----------- */

	/* failed transaction handling */
	if ((failed_transaction_flag != -1) && 
		!flag_in_range(failed_transaction_flag)) {
		LM_ERR("failed_transaction_flag set to invalid value\n");
		return -1;
	}
	if (failed_filter_str) {
	    if (parse_failed_filter(failed_filter_str, failed_filter) == 0) {
		LM_ERR("failed to parse failed_filter param\n");
		return -1;
	    }
	} else {
	    failed_filter[0] = 0;
	}

	/* load the TM API */
	if (load_tm_api(&tmb)!=0) {
		LM_ERR("can't load TM API\n");
		return -1;
	}

	/* if detect_direction is enabled, load rr also */
	if (detect_direction) {
		if (load_rr_api(&rrb)!=0) {
			LM_ERR("can't load RR API\n");
			return -1;
		}
		/* we need the append_fromtag on in RR */
		if (!rrb.append_fromtag) {
			LM_ERR("'append_fromtag' RR param is not enabled!"
				" - required by 'detect_direction'\n");
			return -1;
		}
	}

	/* listen for all incoming requests  */
	if ( tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, acc_onreq, 0, 0 ) <=0 ) {
		LM_ERR("cannot register TMCB_REQUEST_IN callback\n");
		return -1;
	}

	/* configure multi-leg accounting */
	if (leg_info_str && (leg_info=parse_acc_leg(leg_info_str))==0 ) {
		LM_ERR("failed to parse multileg_info param\n");
		return -1;
	}

	/* ----------- SYSLOG INIT SECTION ----------- */

	/* parse the extra string, if any */
	if (log_extra_str && (log_extra=parse_acc_extra(log_extra_str))==0 ) {
		LM_ERR("failed to parse log_extra param\n");
		return -1;
	}

	if ((log_flag != -1) && !flag_in_range(log_flag)) {
		LM_ERR("log_flag set to invalid value\n");
		return -1;
	}

	if ((log_missed_flag != -1) && !flag_in_range(log_missed_flag)) {
		LM_ERR("log_missed_flag set to invalid value\n");
		return -1;
	}

	acc_log_init();

	/* ----------- INIT CDR GENERATION ----------- */

	if( cdr_enable < 0 || cdr_enable > 1)
	{
		LM_ERR("cdr_enable is out of range\n");
		return -1;
	}

	if( cdr_expired_dlg_enable < 0 || cdr_expired_dlg_enable > 1)
	{
		LM_ERR("cdr_expired_dlg_enable is out of range\n");
		return -1;
	}

	if( cdr_enable)
	{
		if( !cdr_start_str.s || !cdr_end_str.s || !cdr_duration_str.s) 
		{
		      LM_ERR( "necessary cdr_parameters are not set\n");
		      return -1;
		}			
		
		if( !cdr_start_str.len || !cdr_end_str.len || !cdr_duration_str.len) 
		{
		      LM_ERR( "necessary cdr_parameters are empty\n");
		      return -1;
		}
		
		
		if( set_cdr_extra( cdr_log_extra_str) != 0)
		{
			LM_ERR( "failed to set cdr extra '%s'\n", cdr_log_extra_str);
			return -1;
		}

		if( cdr_facility_str && set_cdr_facility( cdr_facility_str) != 0)
		{
			LM_ERR( "failed to set cdr facility '%s'\n", cdr_facility_str);
			return -1;
		}
	
		if( init_cdr_generation() != 0)
		{
			LM_ERR("failed to init cdr generation\n");
			return -1;
		}
	}

	/* ------------ SQL INIT SECTION ----------- */

#ifdef SQL_ACC
	if (db_url.s && db_url.len > 0) {
		/* parse the extra string, if any */
		if (db_extra_str && (db_extra=parse_acc_extra(db_extra_str))==0 ) {
			LM_ERR("failed to parse db_extra param\n");
			return -1;
		}
		if (acc_db_init(&db_url)<0){
			LM_ERR("failed...did you load a database module?\n");
			return -1;
		}
		/* fix the flags */

		if ((db_flag != -1) && !flag_in_range(db_flag)) {
			LM_ERR("db_flag set to invalid value\n");
			return -1;
		}

		if ((db_missed_flag != -1) && !flag_in_range(db_missed_flag)) {
			LM_ERR("db_missed_flag set to invalid value\n");
			return -1;
		}
	} else {
		db_url.s = NULL;
		db_url.len = 0;
		db_flag = -1;
		db_missed_flag = -1;
	}
#endif

	/* ------------ RADIUS INIT SECTION ----------- */

#ifdef RAD_ACC
	if (radius_config && radius_config[0]) {
		/* parse the extra string, if any */
		if (rad_extra_str && (rad_extra=parse_acc_extra(rad_extra_str))==0 ) {
			LM_ERR("failed to parse rad_extra param\n");
			return -1;
		}

		/* fix the flags */
		if ((radius_flag != -1) && !flag_in_range(radius_flag)) {
			LM_ERR("radius_flag set to invalid value\n");
			return -1;
		}

		if ((radius_missed_flag != -1) && !flag_in_range(radius_missed_flag)) {
			LM_ERR("radius_missed_flag set to invalid value\n");
			return -1;
		}

		if (init_acc_rad( radius_config, service_type)!=0 ) {
			LM_ERR("failed to init radius\n");
			return -1;
		}
	} else {
		radius_config = 0;
		radius_flag = -1;
		radius_missed_flag = -1;
	}
#endif

	/* ------------ DIAMETER INIT SECTION ----------- */

#ifdef DIAM_ACC
	/* fix the flags */
	if (flag_idx2mask(&diameter_flag)<0)
		return -1;
	if (flag_idx2mask(&diameter_missed_flag)<0)
		return -1;

	/* parse the extra string, if any */
	if (dia_extra_str && (dia_extra=parse_acc_extra(dia_extra_str))==0 ) {
		LM_ERR("failed to parse dia_extra param\n");
		return -1;
	}

	if (acc_diam_init()!=0) {
		LM_ERR("failed to init diameter engine\n");
		return -1;
	}

#endif

	_acc_module_initialized = 1;
	if(acc_init_engines()<0) {
		LM_ERR("failed to init extra engines\n");
		return -1;
	}

	return 0;
}
示例#7
0
/*! \brief Adds the proxies in the proxy list & resolves the hostnames 
 * \return 0 if ok, <0 on error */
static int fix_actions(struct action* a)
{
	struct action *t;
	int ret;
	cmd_export_t* cmd;
	struct hostent* he;
	struct ip_addr ip;
	struct socket_info* si;
	str host;
	int proto=PROTO_NONE, port;
	struct proxy_l *p;
	struct bl_head *blh;
	int i;
	str s;
	pv_elem_t *model=NULL;
	pv_elem_t *models[5]; 
	xl_level_p xlp;

	if (a==0){
		LM_CRIT("null pointer\n");
		return E_BUG;
	}
	for(t=a; t!=0; t=t->next){
		switch(t->type){
			case ROUTE_T:
				if (t->elem[0].type!=NUMBER_ST){
					LM_ALERT("BUG in route() type %d\n",
						t->elem[0].type);
					ret = E_BUG;
					goto error;
				}
				if ((t->elem[0].u.number>RT_NO)||(t->elem[0].u.number<0)){
					LM_ALERT("invalid routing table number in"
							"route(%lu)\n", t->elem[0].u.number);
					ret = E_CFG;
					goto error;
				}
				if ( rlist[t->elem[0].u.number].a==NULL ) {
					LM_ERR("called route %d is not defined\n",
						(int)t->elem[0].u.number);
					ret = E_CFG;
					goto error;
				}
				break;
			case FORWARD_T:
				if (sl_fwd_disabled>0) {
					LM_ERR("stateless forwarding disabled, but forward() "
						"is used!!\n");
					ret = E_CFG;
					goto error;
				}
				sl_fwd_disabled = 0;
				if (t->elem[0].type==NOSUBTYPE)
					break;
			case SEND_T:
				if (t->elem[0].type!=STRING_ST) {
					LM_CRIT("invalid type %d (should be string)\n", t->type);
					ret = E_BUG;
					goto error;
				}
				ret = parse_phostport( t->elem[0].u.string,
						strlen(t->elem[0].u.string),
						&host.s, &host.len, &port, &proto);
				if (ret!=0) {
					LM_ERR("ERROR:fix_actions: FORWARD/SEND bad "
						"argument\n");
					ret = E_CFG;
					goto error;
				}
				p = add_proxy( &host,(unsigned short)port, proto);
				if (p==0) {
					LM_ERR("forward/send failed to add proxy");
					ret = E_CFG;
					goto error;
				}
				t->elem[0].type = PROXY_ST;
				t->elem[0].u.data = (void*)p;
				break;
			case IF_T:
				if (t->elem[0].type!=EXPR_ST){
					LM_CRIT("invalid subtype %d for if (should be expr)\n",
								t->elem[0].type);
					ret = E_BUG;
					goto error;
				}else if( (t->elem[1].type!=ACTIONS_ST)
						&&(t->elem[1].type!=NOSUBTYPE) ){
					LM_CRIT("invalid subtype %d for if() {...} (should be"
								"action)\n", t->elem[1].type);
					ret = E_BUG;
					goto error;
				}else if( (t->elem[2].type!=ACTIONS_ST)
						&&(t->elem[2].type!=NOSUBTYPE) ){
					LM_CRIT("invalid subtype %d for if() {} else{...}(should"
							"be action)\n", t->elem[2].type);
					ret = E_BUG;
					goto error;
				}
				if (t->elem[0].u.data){
					if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0)
						return ret;
				}
				if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0)
						return ret;
				}
				if ( (t->elem[2].type==ACTIONS_ST)&&(t->elem[2].u.data) ){
					if((ret=fix_actions((struct action*)t->elem[2].u.data))<0)
						return ret;
				}
				break;
			case WHILE_T:
				if (t->elem[0].type!=EXPR_ST){
					LM_CRIT("invalid subtype %d for while (should be expr)\n",
								t->elem[0].type);
					ret = E_BUG;
					goto error;
				}else if( (t->elem[1].type!=ACTIONS_ST)
						&&(t->elem[1].type!=NOSUBTYPE) ){
					LM_CRIT("invalid subtype %d for while() {...} (should be"
								"action)\n", t->elem[1].type);
					ret = E_BUG;
					goto error;
				}
				if (t->elem[0].u.data){
					if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0)
						return ret;
				}
				if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0)
						return ret;
				}
				break;
			case SWITCH_T:
				if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0)
						return ret;
				}
				break;
			case CASE_T:
				if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0)
						return ret;
				}
				break;
			case DEFAULT_T:
				if ( (t->elem[0].type==ACTIONS_ST)&&(t->elem[0].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[0].u.data))<0)
						return ret;
				}
				break;
			case MODULE_T:
				cmd = (cmd_export_t*)t->elem[0].u.data;
				LM_DBG("fixing %s, line %d\n", cmd->name, t->line);
				if (cmd->fixup){
					if (cmd->param_no==0){
						ret=cmd->fixup( 0, 0);
						if (ret<0) goto error;
					}
					else {
						for (i=1; i<=cmd->param_no; i++) {
							ret=cmd->fixup(&t->elem[i].u.data, i);
							t->elem[i].type=MODFIXUP_ST;
							if (ret<0) goto error;
						}
					}
				}
				break;
			case FORCE_SEND_SOCKET_T:
				if (t->elem[0].type!=SOCKID_ST){
					LM_CRIT("invalid subtype %d for force_send_socket\n",
								t->elem[0].type);
					ret = E_BUG;
					goto error;
				}
				he=resolvehost(((struct socket_id*)t->elem[0].u.data)->name,0);
				if (he==0){
					LM_ERR(" could not resolve %s\n",
								((struct socket_id*)t->elem[0].u.data)->name);
					ret = E_BAD_ADDRESS;
					goto error;
				}
				hostent2ip_addr(&ip, he, 0);
				si=find_si(&ip, ((struct socket_id*)t->elem[0].u.data)->port,
								((struct socket_id*)t->elem[0].u.data)->proto);
				if (si==0){
					LM_ERR("bad force_send_socket"
						" argument: %s:%d (opensips doesn't listen on it)\n",
						((struct socket_id*)t->elem[0].u.data)->name,
						((struct socket_id*)t->elem[0].u.data)->port);
					ret = E_BAD_ADDRESS;
					goto error;
				}
				t->elem[0].u.data=si;
				t->elem[0].type=SOCKETINFO_ST;
				break;
			case SET_DEBUG_T:
				if (t->elem[0].type==NOSUBTYPE)
					break;
				if (t->elem[0].type!=NUMBER_ST) {
					LM_CRIT("fix_actions: BUG in setdebug() type %d\n",
						t->elem[0].type );
					ret=E_BUG;
					goto error;
				}
				/* normalize the value */
				if (t->elem[0].u.number>L_DBG)
					t->elem[0].u.number = L_DBG;
				else if (t->elem[0].u.number<L_ALERT)
					t->elem[0].u.number = L_ALERT;
				break;
			case SETFLAG_T:
			case RESETFLAG_T:
			case ISFLAGSET_T:
				if (t->elem[0].type!=NUMBER_ST) {
					LM_CRIT("bad xxxflag() type %d\n", t->elem[0].type );
					ret=E_BUG;
					goto error;
				}
				if (!flag_in_range( t->elem[0].u.number )) {
					ret=E_CFG;
					goto error;
				}
				break;
			case SETSFLAG_T:
			case RESETSFLAG_T:
			case ISSFLAGSET_T:
				if (t->elem[0].type!=NUMBER_ST) {
					LM_CRIT("bad xxxsflag() type %d\n", t->elem[0].type );
					ret=E_BUG;
					goto error;
				}
				t->elem[0].u.number = fixup_flag( t->elem[0].u.number );
				if (t->elem[0].u.data==0) {
					ret=E_CFG;
					goto error;
				}
				break;
			case SETBFLAG_T:
			case RESETBFLAG_T:
			case ISBFLAGSET_T:
				if (t->elem[0].type!=NUMBER_ST || t->elem[1].type!=NUMBER_ST) {
					LM_CRIT("bad xxxbflag() type "
						"%d,%d\n", t->elem[0].type, t->elem[0].type);
					ret=E_BUG;
					goto error;
				}
				t->elem[1].u.number = fixup_flag( t->elem[1].u.number );
				if (t->elem[1].u.data==0) {
					ret=E_CFG;
					goto error;
				}
				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:
				if (t->elem[1].u.data){
					if ((ret=fix_expr((struct expr*)t->elem[1].u.data))<0)
						return ret;
				}
				break;
			case USE_BLACKLIST_T:
			case UNUSE_BLACKLIST_T:
				if (t->elem[0].type!=STRING_ST) {
					LM_CRIT("bad [UN]USE_BLACKLIST type %d\n",t->elem[0].type);
					ret=E_BUG;
					goto error;
				}
				host.s = t->elem[0].u.string;
				host.len = strlen(host.s);
				if ( strcasecmp(host.s,"all")==0 ) {
					blh = NULL;
				} else {
					blh = get_bl_head_by_name(&host);
					if (blh==NULL) {
						LM_ERR("[UN]USE_BLACKLIST - list "
							"%s not configured\n", t->elem[0].u.string);
						ret=E_CFG;
						goto error;
					}
				}
				t->elem[0].type = BLACKLIST_ST;
				t->elem[0].u.data = blh;
				break;
			case CACHE_STORE_T:
			case CACHE_FETCH_T:
			case CACHE_REMOVE_T:
				/* attr name */
				s.s = (char*)t->elem[1].u.data;
				s.len = strlen(s.s);
				if(s.len==0) {
					LM_ERR("param 2 is empty string!\n");
					return E_CFG;
				}

				if(pv_parse_format(&s ,&model) || model==NULL) {
						LM_ERR("wrong format [%s] for value param!\n", s.s);
						ret=E_BUG;
						goto error;
				}
				t->elem[1].u.data = (void*)model;

				if (t->type==CACHE_REMOVE_T)
					break;

				/* value */
				if (t->type==CACHE_FETCH_T) {
					if(((pv_spec_p)t->elem[2].u.data)->type!= PVT_AVP)
					{
						LM_ERR("Wrong type for the third argument - "
							"must be an AVP\n");
						ret=E_BUG;
						goto error;
					}
				} else {
					s.s = (char*)t->elem[2].u.data;
					s.len = strlen(s.s);
					if(s.len==0) {
						LM_ERR("param 2 is empty string!\n");
						return E_CFG;
					}

					if(pv_parse_format(&s ,&model) || model==NULL) {
						LM_ERR("wrong format [%s] for value param!\n",s.s);
						ret=E_BUG;
						goto error;
					}
					t->elem[2].u.data = (void*)model;
				}

				break;
			case XDBG_T:
			case XLOG_T:
				s.s = (char*)t->elem[1].u.data;
				if (s.s == NULL)
				{
					/* commands have only one parameter */
					s.s = (char *)t->elem[0].u.data;
					s.len = strlen(s.s);
					if(s.len==0)
					{
						LM_ERR("param is empty string!\n");
						return E_CFG;
					}

					if(pv_parse_format(&s ,&model) || model==NULL)
					{
						LM_ERR("wrong format [%s] for value param!\n", s.s);
						ret=E_BUG;
						goto error;
					}
					
					t->elem[0].u.data = (void*)model;
					t->elem[0].type = SCRIPTVAR_ELEM_ST;
				}
				else
				{
					/* there are two parameters */
					s.s = (char *)t->elem[0].u.data;
					s.len = strlen(s.s);
					if (s.len == 0)
					{
						LM_ERR("param is empty string\n");
						return E_CFG;
					}
					xlp = (xl_level_p)pkg_malloc(sizeof(xl_level_t));
					if(xlp == NULL)
					{
						LM_ERR("no more memory\n");
						return E_UNSPEC;
					}

					memset(xlp, 0, sizeof(xl_level_t));
					if(s.s[0]==PV_MARKER)
					{
						xlp->type = 1;
						if(pv_parse_spec(&s, &xlp->v.sp)==NULL)
						{
							LM_ERR("invalid level param\n");
							return E_UNSPEC;
						}
					} 
					else 
					{
						xlp->type = 0;
						switch(s.s[2])
						{
							case 'A': xlp->v.level = L_ALERT; break;
							case 'C': xlp->v.level = L_CRIT; break;
							case 'E': xlp->v.level = L_ERR; break;
							case 'W': xlp->v.level = L_WARN; break;
							case 'N': xlp->v.level = L_NOTICE; break;
							case 'I': xlp->v.level = L_INFO; break;
							case 'D': xlp->v.level = L_DBG; break;
							default:
								LM_ERR("unknown log level\n");
								return E_UNSPEC;
						}
					}
					t->elem[0].u.data = xlp;

					s.s = t->elem[1].u.data;
					s.len = strlen(s.s);
					if (pv_parse_format(&s, &model) || model == NULL)
					{
						LM_ERR("wrong fomat [%s] for value param\n",s.s);
						ret=E_BUG;
						goto error;
					}

					t->elem[1].u.data = model;
					t->elem[1].type = SCRIPTVAR_ELEM_ST;
				}
				break;
			case CONSTRUCT_URI_T:
				for (i=0;i<5;i++)
				{	
					s.s = (char*)t->elem[i].u.data;
					s.len = strlen(s.s);
					if(s.len==0) 
						continue;

					if(pv_parse_format(&s ,&(models[i])) || models[i]==NULL) 
					{
						LM_ERR("wrong format [%s] for value param!\n",s.s);
						ret=E_BUG;
						goto error;
					}

					t->elem[i].u.data = (void*)models[i];
				}
				
				if (((pv_spec_p)t->elem[5].u.data)->type != PVT_AVP)
				{
					LM_ERR("Wrong type for the third argument - "
						"must be an AVP\n");
					ret=E_BUG;
					goto error;
				}

				break;
		}
	}
	return 0;
error:
	LM_ERR("fixing failed (code=%d) at cfg line %d\n", ret, t->line);
	return ret;
}
示例#8
0
/* returns 0 if ok, <0 on error */
static int fix_actions(struct action* a)
{
	struct action *t;
	int ret;
	cmd_export_t* cmd;
	struct hostent* he;
	struct ip_addr ip;
	struct socket_info* si;
	str host;
	int proto=PROTO_NONE, port;
	struct proxy_l *p;
	struct bl_head *blh;

	if (a==0){
		LM_CRIT("null pointer\n");
		return E_BUG;
	}
	for(t=a; t!=0; t=t->next){
		switch(t->type){
			case FORWARD_T:
				if (t->elem[0].type==NOSUBTYPE)
					break;
			case SEND_T:
				if (t->elem[0].type!=STRING_ST) {
					LM_CRIT("invalid type %d (should be string)\n", t->type);
					return E_BUG;
				}
				ret = parse_phostport( t->elem[0].u.string,
						strlen(t->elem[0].u.string),
						&host.s, &host.len, &port, &proto);
				if (ret!=0) {
					LM_ERR("ERROR:fix_actions: FORWARD/SEND bad "
						"argument\n");
					return E_CFG;
				}
				p = add_proxy( &host,(unsigned short)port, proto);
				if (p==0) {
					LM_ERR("forward/send failed to add proxy");
					return E_CFG;
				}
				t->elem[0].type = PROXY_ST;
				t->elem[0].u.data = (void*)p;
				break;
			case IF_T:
				if (t->elem[0].type!=EXPR_ST){
					LM_CRIT("invalid subtype %d for if (should be expr)\n",
								t->elem[0].type);
					return E_BUG;
				}else if( (t->elem[1].type!=ACTIONS_ST)
						&&(t->elem[1].type!=NOSUBTYPE) ){
					LM_CRIT("invalid subtype %d for if() {...} (should be"
								"action)\n", t->elem[1].type);
					return E_BUG;
				}else if( (t->elem[2].type!=ACTIONS_ST)
						&&(t->elem[2].type!=NOSUBTYPE) ){
					LM_CRIT("invalid subtype %d for if() {} else{...}(should"
							"be action)\n", t->elem[2].type);
					return E_BUG;
				}
				if (t->elem[0].u.data){
					if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0)
						return ret;
				}
				if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0)
						return ret;
				}
				if ( (t->elem[2].type==ACTIONS_ST)&&(t->elem[2].u.data) ){
					if((ret=fix_actions((struct action*)t->elem[2].u.data))<0)
						return ret;
				}
				break;
			case WHILE_T:
				if (t->elem[0].type!=EXPR_ST){
					LM_CRIT("invalid subtype %d for while (should be expr)\n",
								t->elem[0].type);
					return E_BUG;
				}else if( (t->elem[1].type!=ACTIONS_ST)
						&&(t->elem[1].type!=NOSUBTYPE) ){
					LM_CRIT("invalid subtype %d for while() {...} (should be"
								"action)\n", t->elem[1].type);
					return E_BUG;
				}
				if (t->elem[0].u.data){
					if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0)
						return ret;
				}
				if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0)
						return ret;
				}
				break;
			case SWITCH_T:
				if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0)
						return ret;
				}
				break;
			case CASE_T:
				if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0)
						return ret;
				}
				break;
			case DEFAULT_T:
				if ( (t->elem[0].type==ACTIONS_ST)&&(t->elem[0].u.data) ){
					if ((ret=fix_actions((struct action*)t->elem[0].u.data))<0)
						return ret;
				}
				break;
			case MODULE_T:
				cmd = (cmd_export_t*)t->elem[0].u.data;
				LM_DBG("fixing %s, line %d\n", cmd->name, t->line);
				if (cmd->fixup){
					if (cmd->param_no>0){
						ret=cmd->fixup(&t->elem[1].u.data, 1);
						t->elem[1].type=MODFIXUP_ST;
						if (ret<0) goto error;
					}
					if (cmd->param_no>1){
						ret=cmd->fixup(&t->elem[2].u.data, 2);
						t->elem[2].type=MODFIXUP_ST;
						if (ret<0) goto error;
					}
					if (cmd->param_no==0){
						ret=cmd->fixup( 0, 0);
						if (ret<0) goto error;
					}
				}
				break;
			case FORCE_SEND_SOCKET_T:
				if (t->elem[0].type!=SOCKID_ST){
					LM_CRIT("invalid subtype %d for force_send_socket\n",
								t->elem[0].type);
					return E_BUG;
				}
				he=resolvehost(((struct socket_id*)t->elem[0].u.data)->name,0);
				if (he==0){
					LM_ERR(" could not resolve %s\n",
								((struct socket_id*)t->elem[0].u.data)->name);
					ret = E_BAD_ADDRESS;
					goto error;
				}
				hostent2ip_addr(&ip, he, 0);
				si=find_si(&ip, ((struct socket_id*)t->elem[0].u.data)->port,
								((struct socket_id*)t->elem[0].u.data)->proto);
				if (si==0){
					LM_ERR("bad force_send_socket"
							" argument: %s:%d (ser doesn't listen on it)\n",
							((struct socket_id*)t->elem[0].u.data)->name,
							((struct socket_id*)t->elem[0].u.data)->port);
					ret = E_BAD_ADDRESS;
					goto error;
				}
				t->elem[0].u.data=si;
				t->elem[0].type=SOCKETINFO_ST;
				break;
			case SET_DEBUG_T:
				if (t->elem[0].type==NOSUBTYPE)
					break;
				if (t->elem[0].type!=NUMBER_ST) {
					LM_CRIT("fix_actions: BUG in setdebug() type %d\n",
						t->elem[0].type );
					ret=E_BUG;
					goto error;
				}
				/* normalize the value */
				if (t->elem[0].u.number>L_DBG)
					t->elem[0].u.number = L_DBG;
				else if (t->elem[0].u.number<L_ALERT)
					t->elem[0].u.number = L_ALERT;
				break;
			case SETFLAG_T:
			case RESETFLAG_T:
			case ISFLAGSET_T:
				if (t->elem[0].type!=NUMBER_ST) {
					LM_CRIT("bad xxxflag() type %d\n", t->elem[0].type );
					ret=E_BUG;
					goto error;
				}
				if (!flag_in_range( t->elem[0].u.number )) {
					ret=E_CFG;
					goto error;
				}
				break;
			case SETSFLAG_T:
			case RESETSFLAG_T:
			case ISSFLAGSET_T:
				if (t->elem[0].type!=NUMBER_ST) {
					LM_CRIT("bad xxxsflag() type %d\n", t->elem[0].type );
					ret=E_BUG;
					goto error;
				}
				t->elem[0].u.number = fixup_flag( t->elem[0].u.number );
				if (t->elem[0].u.data==0) {
					ret=E_CFG;
					goto error;
				}
				break;
			case SETBFLAG_T:
			case RESETBFLAG_T:
			case ISBFLAGSET_T:
				if (t->elem[0].type!=NUMBER_ST || t->elem[1].type!=NUMBER_ST) {
					LM_CRIT("bad xxxbflag() type "
						"%d,%d\n", t->elem[0].type, t->elem[0].type);
					ret=E_BUG;
					goto error;
				}
				t->elem[1].u.number = fixup_flag( t->elem[1].u.number );
				if (t->elem[1].u.data==0) {
					ret=E_CFG;
					goto error;
				}
				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:
				if (t->elem[1].u.data){
					if ((ret=fix_expr((struct expr*)t->elem[1].u.data))<0)
						return ret;
				}
				break;
			case USE_BLACKLIST_T:
				if (t->elem[0].type!=STRING_ST) {
					LM_CRIT("bad USE_BLACKLIST type %d\n", t->elem[0].type);
					ret=E_BUG;
					goto error;
				}
				host.s = t->elem[0].u.string;
				host.len = strlen(host.s);
				blh = get_bl_head_by_name(&host);
				if (blh==NULL) {
					LM_ERR("USE_BLACKLIST - list "
						"%s not configured\n", t->elem[0].u.string);
					ret=E_CFG;
					goto error;
				}
				t->elem[0].type = BLACKLIST_ST;
				t->elem[0].u.data = blh;
				break;
		}
	}
	return 0;
error:
	LM_ERR("fixing failed (code=%d) at cfg line %d\n", ret, t->line);
	return ret;
}
示例#9
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;
}