Пример #1
0
/* 
 * Check if an entry exists in hash table that has given src_ip and protocol
 * value and pattern that matches to From URI.  If an entry exists and tag_avp
 * has been defined, tag of the entry is added as a value to tag_avp.
 * Returns number of matches or -1 if none matched.
 */
int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
		char *src_ip_c_str, int proto)
{
	str uri;
	char uri_string[MAX_URI_SIZE + 1];
	regex_t preg;
	struct trusted_list *np;
	str src_ip;
	int_str val;
	int count = 0;

	src_ip.s = src_ip_c_str;
	src_ip.len = strlen(src_ip.s);

	if (IS_SIP(msg))
	{
		if (parse_from_header(msg) < 0) return -1;
		uri = get_from(msg)->uri;
		if (uri.len > MAX_URI_SIZE) {
			LM_ERR("from URI too large\n");
			return -1;
		}
		memcpy(uri_string, uri.s, uri.len);
		uri_string[uri.len] = (char)0;
	}

	for (np = table[perm_hash(src_ip)]; np != NULL; np = np->next) {
	    if ((np->src_ip.len == src_ip.len) && 
		(strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
		((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
		 (np->proto == proto))) {
		if (np->pattern && IS_SIP(msg)) {
		    if (regcomp(&preg, np->pattern, REG_NOSUB)) {
			LM_ERR("invalid regular expression\n");
			continue;
		    }
		    if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
			regfree(&preg);
			continue;
		    }
		    regfree(&preg);
		}
		/* Found a match */
		if (tag_avp.n && np->tag.s) {
		    val.s = np->tag;
		    if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
			LM_ERR("setting of tag_avp failed\n");
			return -1;
		    }
		}
		if (!peer_tag_mode)
		    return 1;
		count++;
	    }
	}
	if (!count)
	    return -1;
	else 
	    return count;
}
Пример #2
0
int th_prepare_msg(sip_msg_t *msg)
{
	if (parse_msg(msg->buf, msg->len, msg)!=0)
	{
		LM_DBG("outbuf buffer parsing failed!");
		return 1;
	}

	if(msg->first_line.type==SIP_REQUEST)
	{
		if(!IS_SIP(msg))
		{
			LM_DBG("non sip request message\n");
			return 1;
		}
	} else if(msg->first_line.type!=SIP_REPLY) {
		LM_DBG("non sip message\n");
		return 1;
	}

	if (parse_headers(msg, HDR_EOH_F, 0)==-1)
	{
		LM_DBG("parsing headers failed [[%.*s]]\n",
				msg->len, msg->buf);
		return 2;
	}

	/* force 2nd via parsing here - it helps checking it later */
	if (parse_headers(msg, HDR_VIA2_F, 0)==-1
		|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
	{
		LM_DBG("no second via in this message \n");
	}

	if(parse_from_header(msg)<0)
	{
		LM_ERR("cannot parse FROM header\n");
		return 3;
	}

	if(parse_to_header(msg)<0 || msg->to==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		return 3;
	}

	if(get_to(msg)==NULL)
	{
		LM_ERR("cannot get TO header\n");
		return 3;
	}

	if(msg->via1==NULL || msg->callid==NULL) {
		LM_ERR("mandatory headers missing - via1: %p callid: %p\n",
				msg->via1, msg->callid);
		return 4;
	}

	return 0;
}
Пример #3
0
int gzc_prepare_msg(sip_msg_t *msg)
{
	if (parse_msg(msg->buf, msg->len, msg)!=0)
	{
		LM_DBG("outbuf buffer parsing failed!");
		return 1;
	}

	if(msg->first_line.type==SIP_REQUEST)
	{
		if(!IS_SIP(msg) && !IS_HTTP(msg))
		{
			LM_DBG("non sip or http request\n");
			return 1;
		}
	} else if(msg->first_line.type==SIP_REPLY) {
		if(!IS_SIP_REPLY(msg) && !IS_HTTP_REPLY(msg))
		{
			LM_DBG("non sip or http response\n");
			return 1;
		}
	} else {
		LM_DBG("non sip or http message\n");
		return 1;
	}

	if (parse_headers(msg, HDR_EOH_F, 0)==-1)
	{
		LM_DBG("parsing headers failed");
		return 2;
	}

	return 0;
}
Пример #4
0
static int km_cb_req_stats(struct sip_msg *msg,
		unsigned int flags, void *param)
{
	update_stat(rcv_reqs, 1);
	if(!IS_SIP(msg))
		return 1;
	if(msg->first_line.u.request.method_value==METHOD_OTHER)
		update_stat(unsupported_methods, 1);
	return 1;
}
Пример #5
0
static int dlg_cseq_prepare_msg(sip_msg_t *msg)
{
	LM_DBG("prepare msg for cseq update operations\n");

	if(msg->first_line.type==SIP_REQUEST) {
		if(!IS_SIP(msg)) {
			LM_DBG("non sip request message\n");
			return 1;
		}
	} else if(msg->first_line.type==SIP_REPLY) {
		if(!IS_SIP_REPLY(msg)) {
			LM_DBG("non sip reply message\n");
			return 1;
		}
	} else {
		LM_DBG("non sip message\n");
		return 1;
	}

	if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
		|| !msg->cseq->parsed){
		LM_DBG("parsing cseq header failed\n");
		return 2;
	}

	if(msg->first_line.type==SIP_REPLY) {
		/* reply to local transaction -- nothing to do */
		if (parse_headers(msg, HDR_VIA2_F, 0)==-1
				|| (msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
			if(get_cseq(msg)->method_id != METHOD_CANCEL) {
				LM_DBG("no second via in this message \n");
				return 3;
			}
		}
	}

	if(parse_from_header(msg)<0) {
		LM_ERR("cannot parse FROM header\n");
		return 3;
	}

	if(parse_to_header(msg)<0 || msg->to==NULL) {
		LM_ERR("cannot parse TO header\n");
		return 3;
	}

	if(get_to(msg)==NULL) {
		LM_ERR("cannot get TO header\n");
		return 3;
	}

	return 0;
}
Пример #6
0
int dlg_cseq_prepare_msg(sip_msg_t *msg)
{
	if (parse_msg(msg->buf, msg->len, msg)!=0) {
		LM_DBG("outbuf buffer parsing failed!");
		return 1;
	}

	if(msg->first_line.type==SIP_REQUEST) {
		if(!IS_SIP(msg))
		{
			LM_DBG("non sip request message\n");
			return 1;
		}
	} else if(msg->first_line.type!=SIP_REPLY) {
		LM_DBG("non sip message\n");
		return 1;
	}

	if (parse_headers(msg, HDR_CSEQ_F, 0)==-1) {
		LM_DBG("parsing cseq header failed\n");
		return 2;
	}

	if(msg->first_line.type==SIP_REPLY) {
		/* reply to local transaction -- nothing to do */
		if (parse_headers(msg, HDR_VIA2_F, 0)==-1
				|| (msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
			LM_DBG("no second via in this message \n");
			return 3;
		}
	}

	if(parse_from_header(msg)<0)
	{
		LM_ERR("cannot parse FROM header\n");
		return 3;
	}

	if(parse_to_header(msg)<0 || msg->to==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		return 3;
	}

	if(get_to(msg)==NULL)
	{
		LM_ERR("cannot get TO header\n");
		return 3;
	}

	return 0;
}
Пример #7
0
void log_prefix_set(sip_msg_t *msg)
{
	if(log_prefix_pvs == NULL)
		return;
	if(msg==NULL || !(IS_SIP(msg) || IS_SIP_REPLY(msg))) {
		log_prefix_val = NULL;
		return;
	}
	log_prefix_str.s = log_prefix_buf;
	log_prefix_str.len = LOG_PREFIX_SIZE;
	if(pv_printf(msg, log_prefix_pvs, log_prefix_str.s, &log_prefix_str.len)<0)
		return;
	if(log_prefix_str.len<=0)
		return;
	log_prefix_val = &log_prefix_str;
}
Пример #8
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;
	struct run_act_ctx ctx;
	int ret;
#ifdef STATS
	int skipped = 1;
	struct timeval tvb, tve;	
	struct timezone tz;
	unsigned int diff;
#endif
	str inb;

	inb.s = buf;
	inb.len = len;
	sr_event_exec(SREV_NET_DATA_IN, (void*)&inb);
	len = inb.len;

	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->pid=my_pid();
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;
	
	if(likely(sr_msg_time==1)) msg_set_time(msg);

	if (parse_msg(buf,len, msg)!=0){
		if(sr_event_exec(SREV_RCV_NOSIP, (void*)msg)!=0) {
			LOG(cfg_get(core, core_cfg, corelog),
				"core parsing of SIP message failed (%s:%d/%d)\n",
				ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
				(int)msg->rcv.proto);
			sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
		}
		goto error02;
	}
	DBG("After parse_msg...\n");


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

	if (msg->first_line.type==SIP_REQUEST){
		ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
		if (!IS_SIP(msg)){
			if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
				if (unlikely(ret==NONSIP_MSG_ERROR))
					goto error03;
				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");
			STATS_BAD_MSG();
			goto error02;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && cfg_get(tcp, tcp_cfg, 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_script_cb(msg, REQUEST_CB_TYPE)==0 )
		{
			STATS_REQ_FWD_DROP();
			goto end; /* drop the request */
		}

		set_route_type(REQUEST_ROUTE);
		/* exec the routing script */
		if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<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_script_cb(msg, REQUEST_CB_TYPE);
	}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");
			STATS_BAD_RPL();
			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_script_cb(msg, ONREPLY_CB_TYPE)==0 )
		{
			STATS_RPL_FWD_DROP();
			goto end; /* drop the reply */
		}

		/* exec the onreply routing script */
		if (onreply_rt.rlist[DEFAULT_RT]){
			set_route_type(CORE_ONREPLY_ROUTE);
			ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
#ifndef NO_ONREPLY_ROUTE_ERROR
			if (unlikely(ret<0)){
				LOG(L_WARN, "WARNING: receive_msg: "
						"error while trying onreply script\n");
				goto error_rpl;
			}else
#endif /* NO_ONREPLY_ROUTE_ERROR */
			if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
				STATS_RPL_FWD_DROP();
				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_script_cb(msg, ONREPLY_CB_TYPE);
	}

end:
#ifdef STATS
	skipped = 0;
#endif
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	DBG("receive_msg: cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
#ifdef STATS
	if (skipped) STATS_RX_DROPS;
#endif
	return 0;
#ifndef NO_ONREPLY_ROUTE_ERROR
error_rpl:
	/* execute post reply-script callbacks */
	exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	goto error02;
#endif /* NO_ONREPLY_ROUTE_ERROR */
error_req:
	DBG("receive_msg: error:...\n");
	/* execute post request-script callbacks */
	exec_post_script_cb(msg, REQUEST_CB_TYPE);
error03:
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
error02:
	free_sip_msg(msg);
	pkg_free(msg);
error00:
	STATS_RX_DROPS;
	return -1;
}
Пример #9
0
/*
 * Matches from uri against patterns returned from database.  Returns number
 * of matches or -1 if none of the patterns match.
 */
static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
{
	int i, tag_avp_type;
	str uri, ruri;
	char uri_string[MAX_URI_SIZE+1];
	char ruri_string[MAX_URI_SIZE+1];
	db_row_t* row;
	db_val_t* val;
	regex_t preg;
	int_str tag_avp, avp_val;
	int count = 0;

	if (IS_SIP(msg)) {
		if (parse_from_header(msg) < 0) return -1;
		uri = get_from(msg)->uri;
		if (uri.len > MAX_URI_SIZE) {
			LM_ERR("message has From URI too large\n");
			return -1;
		}
		memcpy(uri_string, uri.s, uri.len);
		uri_string[uri.len] = (char)0;
		ruri = msg->first_line.u.request.uri;
		if (ruri.len > MAX_URI_SIZE) {
			LM_ERR("message has Request URI too large\n");
			return -1;
		}
		memcpy(ruri_string, ruri.s, ruri.len);
		ruri_string[ruri.len] = (char)0;
	}
	get_tag_avp(&tag_avp, &tag_avp_type);

	row = RES_ROWS(_r);

	for(i = 0; i < RES_ROW_N(_r); i++) {
		val = ROW_VALUES(row + i);
		if ((ROW_N(row + i) == 4) &&
		    (VAL_TYPE(val) == DB1_STRING) && !VAL_NULL(val) &&
		    match_proto(VAL_STRING(val), proto) &&
		    (VAL_NULL(val + 1) ||
		      ((VAL_TYPE(val + 1) == DB1_STRING) && !VAL_NULL(val + 1))) &&
		    (VAL_NULL(val + 2) ||
		      ((VAL_TYPE(val + 2) == DB1_STRING) && !VAL_NULL(val + 2))) &&
		    (VAL_NULL(val + 3) ||
		      ((VAL_TYPE(val + 3) == DB1_STRING) && !VAL_NULL(val + 3))))
		{
			if (IS_SIP(msg)) {
			    if (!VAL_NULL(val + 1)) {
				if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) {
					LM_ERR("invalid regular expression\n");
					if (VAL_NULL(val + 2)) {
						continue;
					}
				}
				if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
					regfree(&preg);
					continue;
				}
				regfree(&preg);
			    }
			    if (!VAL_NULL(val + 2)) {
				if (regcomp(&preg, (char *)VAL_STRING(val + 2), REG_NOSUB)) {
					LM_ERR("invalid regular expression\n");
					continue;
				}
				if (regexec(&preg, ruri_string, 0, (regmatch_t *)0, 0)) {
					regfree(&preg);
					continue;
				}
				regfree(&preg);
			    }
			}
			/* Found a match */
			if (tag_avp.n && !VAL_NULL(val + 3)) {
				avp_val.s.s = (char *)VAL_STRING(val + 3);
				avp_val.s.len = strlen(avp_val.s.s);
				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, avp_val) != 0) {
					LM_ERR("failed to set of tag_avp failed\n");
					return -1;
				}
			}
			if (!peer_tag_mode) 
				return 1;
			count++;
		}
	}
	if (!count)
		return -1;
	else 
		return count;
}
Пример #10
0
/** Receive message
 *  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;
	struct run_act_ctx ctx;
	struct run_act_ctx *bctx;
	int ret;
#ifdef STATS
	int skipped = 1;
	int stats_on = 1;
#else
	int stats_on = 0;
#endif
	struct timeval tvb, tve;
	struct timezone tz;
	unsigned int diff = 0;
	str inb;
	sr_net_info_t netinfo;
	sr_kemi_eng_t *keng = NULL;

	if(sr_event_enabled(SREV_NET_DATA_RECV)) {
		if(sip_check_fline(buf, len)==0) {
			memset(&netinfo, 0, sizeof(sr_net_info_t));
			netinfo.data.s = buf;
			netinfo.data.len = len;
			netinfo.rcv = rcv_info;
			sr_event_exec(SREV_NET_DATA_RECV, (void*)&netinfo);
		}
	}

	inb.s = buf;
	inb.len = len;
	sr_event_exec(SREV_NET_DATA_IN, (void*)&inb);
	len = inb.len;

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LM_ERR("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->pid=my_pid();
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;

	if(likely(sr_msg_time==1)) msg_set_time(msg);

	if (parse_msg(buf,len, msg)!=0){
		if((ret=sr_event_exec(SREV_RCV_NOSIP, (void*)msg))<NONSIP_MSG_DROP) {
			LOG(cfg_get(core, core_cfg, corelog),
				"core parsing of SIP message failed (%s:%d/%d)\n",
				ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
				(int)msg->rcv.proto);
			sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
		}
		else if(ret == NONSIP_MSG_DROP) goto error02;
	}

	parse_headers(msg, HDR_FROM_F|HDR_TO_F|HDR_CALLID_F|HDR_CSEQ_F, 0);
	LM_DBG("--- received sip message - %s - call-id: [%.*s] - cseq: [%.*s]\n",
			(msg->first_line.type==SIP_REQUEST)?"request":"reply",
			(msg->callid && msg->callid->body.s)?msg->callid->body.len:0,
			(msg->callid && msg->callid->body.s)?msg->callid->body.s:"",
			(msg->cseq && msg->cseq->body.s)?msg->cseq->body.len:0,
			(msg->cseq && msg->cseq->body.s)?msg->cseq->body.s:"");

	/* set log prefix */
	log_prefix_set(msg);

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

	if (msg->first_line.type==SIP_REQUEST){
		ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
		if (!IS_SIP(msg)){
			if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
				if (unlikely(ret==NONSIP_MSG_ERROR))
					goto error03;
				goto end; /* drop the message */
			}
		}
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in request\n");
			STATS_BAD_MSG();
			goto error02;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && cfg_get(tcp, tcp_cfg, 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){
				LM_ERR("tcp alias failed\n");
				/* continue */
			}
		}
#endif

	/*	skip: */
		LM_DBG("preparing to run routing scripts...\n");
		if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
				|| stats_on==1) {
			gettimeofday( & tvb, &tz );
		}
		/* 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_script_cb(msg, REQUEST_CB_TYPE)==0 )
		{
			STATS_REQ_FWD_DROP();
			goto end; /* drop the request */
		}

		set_route_type(REQUEST_ROUTE);
		/* exec the routing script */
		if(unlikely(main_rt.rlist[DEFAULT_RT]==NULL)) {
			keng = sr_kemi_eng_get();
			if(keng==NULL) {
				LM_ERR("no config routing engine registered\n");
				goto error_req;
			}
			if(keng->froute(msg, REQUEST_ROUTE, NULL, NULL)<0) {
				LM_NOTICE("negative return code from engine function\n");
			}
		} else {
			if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){
				LM_WARN("error while trying script\n");
				goto error_req;
			}
		}

		if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
				|| stats_on==1) {
			gettimeofday( & tve, &tz );
			diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
			LOG(cfg_get(core, core_cfg, latency_cfg_log),
					"request-route executed in: %d usec\n", diff);
#ifdef STATS
			stats->processed_requests++;
			stats->acc_req_time += diff;
			STATS_RX_REQUEST( msg->first_line.u.request.method_value );
#endif
		}

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

		if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
				|| stats_on==1) {
			gettimeofday( & tvb, &tz );
		}
#ifdef STATS
		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_script_cb(msg, ONREPLY_CB_TYPE)==0 )
		{
			STATS_RPL_FWD_DROP();
			goto end; /* drop the reply */
		}

		/* exec the onreply routing script */
		keng = sr_kemi_eng_get();
		if (onreply_rt.rlist[DEFAULT_RT]!=NULL || keng!=NULL){
			set_route_type(CORE_ONREPLY_ROUTE);
			ret = 1;
			if(unlikely(keng!=NULL)) {
				bctx = sr_kemi_act_ctx_get();
				init_run_actions_ctx(&ctx);
				sr_kemi_act_ctx_set(&ctx);
				ret = keng->froute(msg, CORE_ONREPLY_ROUTE, NULL, NULL);
				sr_kemi_act_ctx_set(bctx);
			} else {
				ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
			}
#ifndef NO_ONREPLY_ROUTE_ERROR
			if (unlikely(ret<0)){
				LM_WARN("error while trying onreply script\n");
				goto error_rpl;
			}else
#endif /* NO_ONREPLY_ROUTE_ERROR */
			if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
				STATS_RPL_FWD_DROP();
				goto skip_send_reply; /* drop the message, no error */
			}
		}
		/* send the msg */
		forward_reply(msg);
	skip_send_reply:
		if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
				|| stats_on==1) {
			gettimeofday( & tve, &tz );
			diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
			LOG(cfg_get(core, core_cfg, latency_cfg_log),
					"reply-route executed in: %d usec\n", diff);
#ifdef STATS
			stats->processed_responses++;
			stats->acc_res_time+=diff;
#endif
		}

		/* execute post reply-script callbacks */
		exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	}

end:
#ifdef STATS
	skipped = 0;
#endif
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	LM_DBG("cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
#ifdef STATS
	if (skipped) STATS_RX_DROPS;
#endif
	/* reset log prefix */
	log_prefix_set(NULL);
	return 0;

#ifndef NO_ONREPLY_ROUTE_ERROR
error_rpl:
	/* execute post reply-script callbacks */
	exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	goto error02;
#endif /* NO_ONREPLY_ROUTE_ERROR */
error_req:
	LM_DBG("error:...\n");
	/* execute post request-script callbacks */
	exec_post_script_cb(msg, REQUEST_CB_TYPE);
error03:
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
error02:
	free_sip_msg(msg);
	pkg_free(msg);
error00:
	STATS_RX_DROPS;
	/* reset log prefix */
	log_prefix_set(NULL);
	return -1;
}
Пример #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 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;
}
Пример #12
0
/*!
 * helper function for stateless reply
 */
int sl_reply_helper(struct sip_msg *msg, int code, char *reason, str *tag)
{
    str buf = {0, 0};
    str dset = {0, 0};
    struct dest_info dst;
    struct bookmark dummy_bm;
    int backup_mhomed, ret;
    str text;

    int rt, backup_rt;
    struct run_act_ctx ctx;
    struct sip_msg pmsg;

    if (msg->first_line.u.request.method_value==METHOD_ACK)
        goto error;

    init_dest_info(&dst);
    if (reply_to_via) {
        if (update_sock_struct_from_via(&dst.to, msg, msg->via1 )==-1)
        {
            LOG(L_ERR, "ERROR: sl_reply_helper: cannot lookup reply dst: %s\n",
                msg->via1->host.s);
            goto error;
        }
    } else update_sock_struct_from_ip(&dst.to, msg);

    /* if that is a redirection message, dump current message set to it */
    if (code>=300 && code<400) {
        dset.s=print_dset(msg, &dset.len);
        if (dset.s) {
            add_lump_rpl(msg, dset.s, dset.len, LUMP_RPL_HDR);
        }
    }

    text.s = reason;
    text.len = strlen(reason);

    /* add a to-tag if there is a To header field without it */
    if ( 	/* since RFC3261, we append to-tags anywhere we can, except
		 * 100 replies */
        /* msg->first_line.u.request.method_value==METHOD_INVITE && */
        code>=180 &&
        (msg->to || (parse_headers(msg,HDR_TO_F, 0)!=-1 && msg->to))
        && (get_to(msg)->tag_value.s==0 || get_to(msg)->tag_value.len==0) )
    {
        if(tag!=NULL && tag->s!=NULL) {
            buf.s = build_res_buf_from_sip_req(code, &text, tag,
                                               msg, (unsigned int*)&buf.len, &dummy_bm);
        } else {
            calc_crc_suffix( msg, tag_suffix );
            buf.s = build_res_buf_from_sip_req(code, &text, &sl_tag, msg,
                                               (unsigned int*)&buf.len, &dummy_bm);
        }
    } else {
        buf.s = build_res_buf_from_sip_req(code, &text, 0, msg,
                                           (unsigned int*)&buf.len, &dummy_bm);
    }
    if (!buf.s)
    {
        DBG("DEBUG: sl_reply_helper: response building failed\n");
        goto error;
    }

    sl_run_callbacks(SLCB_REPLY_READY, msg, code, reason, &buf, &dst);

    /* supress multhoming support when sending a reply back -- that makes sure
       that replies will come from where requests came in; good for NATs
       (there is no known use for mhomed for locally generated replies;
        note: forwarded cross-interface replies do benefit of mhomed!
    */
    backup_mhomed=mhomed;
    mhomed=0;
    /* use for sending the received interface -bogdan*/
    dst.proto=msg->rcv.proto;
    dst.send_sock=msg->rcv.bind_address;
    dst.id=msg->rcv.proto_reserved1;
#ifdef USE_COMP
    dst.comp=msg->via1->comp_no;
#endif
    dst.send_flags=msg->rpl_send_flags;
    ret = msg_send(&dst, buf.s, buf.len);
    mhomed=backup_mhomed;

    rt = route_lookup(&event_rt, "sl:local-response");
    if (unlikely(rt >= 0 && event_rt.rlist[rt] != NULL))
    {
        if (likely(build_sip_msg_from_buf(&pmsg, buf.s, buf.len,
                                          inc_msg_no()) == 0))
        {
            char *tmp = NULL;
            struct onsend_info onsnd_info;

            onsnd_info.to=&dst.to;
            onsnd_info.send_sock=dst.send_sock;
            onsnd_info.buf=buf.s;
            onsnd_info.len=buf.len;
            p_onsend=&onsnd_info;

            if (unlikely(!IS_SIP(msg)))
            {
                /* This is an HTTP reply...  So fudge in a CSeq into the parsed message
                   message structure so that $rm will work in the route */
                struct hdr_field *hf;
                struct cseq_body *cseqb;
                char *tmp2;
                int len;

                if ((hf = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field))) == NULL)
                {
                    LM_ERR("out of package memory\n");
                    goto event_route_error;
                }

                if ((cseqb = (struct cseq_body *) pkg_malloc(sizeof(struct cseq_body))) == NULL)
                {
                    LM_ERR("out of package memory\n");
                    pkg_free(hf);
                    goto event_route_error;
                }

                if ((tmp = (char *) pkg_malloc(sizeof(char) * (msg->first_line.u.request.method.len + 5))) == NULL)
                {
                    LM_ERR("out of package memory\n");
                    pkg_free(cseqb);
                    pkg_free(hf);
                    goto event_route_error;
                }

                memset(hf, 0, sizeof(struct hdr_field));
                memset(cseqb, 0, sizeof(struct cseq_body));

                len = sprintf(tmp, "0 %.*s\r\n", msg->first_line.u.request.method.len, msg->first_line.u.request.method.s);
                tmp2 = parse_cseq(tmp, &tmp[len], cseqb);

                hf->type = HDR_CSEQ_T;
                hf->body.s = tmp;
                hf->body.len = tmp2 - tmp;
                hf->parsed = cseqb;

                pmsg.parsed_flag|=HDR_CSEQ_F;
                pmsg.cseq = hf;
                if (pmsg.last_header==0) {
                    pmsg.headers=hf;
                    pmsg.last_header=hf;
                } else {
                    pmsg.last_header->next=hf;
                    pmsg.last_header=hf;
                }
            }

            backup_rt = get_route_type();
            set_route_type(LOCAL_ROUTE);
            init_run_actions_ctx(&ctx);
            run_top_route(event_rt.rlist[rt], &pmsg, 0);
            set_route_type(backup_rt);
            p_onsend=0;

            if (tmp != NULL)
                pkg_free(tmp);

event_route_error:
            free_sip_msg(&pmsg);
        }
    }

    pkg_free(buf.s);

    if (ret<0) {
        goto error;
    }

    *(sl_timeout) = get_ticks() + SL_RPL_WAIT_TIME;

    update_sl_stats(code);
    return 1;

error:
    update_sl_failures();
    return -1;
}