Esempio n. 1
0
/* prepare message and transaction context for later accounting */
void acc_onreq( struct cell* t, int type, struct tmcb_params *ps )
{
	int tmcb_types;
	int is_invite;

	if ( ps->req && !skip_cancel(ps->req) &&
			( is_acc_on(ps->req) || is_mc_on(ps->req)
				|| is_acc_prepare_on(ps->req) ) ) {
		/* do some parsing in advance */
		if (acc_preparse_req(ps->req)<0)
			return;
		is_invite = (ps->req->REQ_METHOD==METHOD_INVITE)?1:0;
		/* install additional handlers */
		tmcb_types =
			/* report on completed transactions */
			TMCB_RESPONSE_OUT |
			/* account e2e acks if configured to do so */
			((report_ack && is_acc_on(ps->req))?TMCB_E2EACK_IN:0) |
			/* get incoming replies ready for processing */
			TMCB_RESPONSE_IN |
			/* report on missed calls */
			((is_invite && (is_mc_on(ps->req)
					|| is_acc_prepare_on(ps->req)))?TMCB_ON_FAILURE:0);
		if (tmb.register_tmcb( 0, t, tmcb_types, tmcb_func, 0, 0 )<=0) {
			LM_ERR("cannot register additional callbacks\n");
			return;
		}
		/* if required, determine request direction */
		if( detect_direction && !rrb.is_direction(ps->req,RR_FLOW_UPSTREAM) ) {
			LM_DBG("detected an UPSTREAM req -> flaging it\n");
			ps->req->msg_flags |= FL_REQ_UPSTREAM;
		}
	}
}
Esempio n. 2
0
int w_acc_db_request(struct sip_msg *rq, pv_elem_t* comment, char *table)
{
	struct acc_param accp;
	int table_len;

	if (!table) {
		LM_ERR("db support not configured\n");
		return -1;
	}

	if (acc_preparse_req(rq)<0)
		return -1;

	table_len = strlen(table);

	acc_pvel_to_acc_param(rq, comment, &accp);

	env_set_to( rq->to );
	env_set_comment( &accp );
	env_set_text(table, table_len);

	if (table_len == db_table_mc.len && (strncmp(table, db_table_mc.s, table_len) == 0)) {
		return acc_db_request(rq, NULL, &mc_ins_list, 0);
	}

	if (table_len == db_table_acc.len && (strncmp(table, db_table_acc.s, table_len) == 0)) {
		return acc_db_request(rq, NULL, &acc_ins_list, 0);
	}

	return acc_db_request( rq, NULL,NULL, 0);
}
Esempio n. 3
0
int w_acc_evi_request(struct sip_msg *rq, pv_elem_t* comment, char *foo)
{
	struct acc_param accp;

	if (acc_preparse_req(rq)<0)
		return -1;

	acc_pvel_to_acc_param(rq, comment, &accp);

	env_set_to( rq->to );
	env_set_comment( &accp );

	if (is_cdr_acc_on(rq) && is_evi_acc_on(rq)) {
		env_set_event(acc_cdr_event);
	} else if (is_evi_acc_on(rq) && acc_env.code < 300) {
		env_set_event(acc_event);
	} else if (is_evi_mc_on(rq)) {
		env_set_event(acc_missed_event);
	} else {
		LM_WARN("evi request flags not set\n");
		return 1;
	}

	return acc_evi_request( rq, NULL, 0);
}
Esempio n. 4
0
static inline void acc_onack( struct cell* t, struct sip_msg *req,
		struct sip_msg *ack, int code)
{
	if (acc_preparse_req(ack)<0)
		return;

	/* set env variables */
	env_set_to( ack->to?ack->to:req->to );
	env_set_code_status( t->uas.status, 0 );

	if (is_log_acc_on(req)) {
		env_set_text( ACC_ACKED, ACC_ACKED_LEN);
		acc_log_request( ack );
	}
#ifdef SQL_ACC
	if (is_db_acc_on(req)) {
		if(acc_db_set_table_name(ack, db_table_acc_data, &db_table_acc)<0) {
			LM_ERR("cannot set acc db table name\n");
			return;
		}
		acc_db_request( ack );
	}
#endif

/* DIAMETER */
#ifdef DIAM_ACC
	if (is_diam_acc_on(req)) {
		acc_diam_request(ack);
	}
#endif

	/* run extra acc engines */
	acc_run_engines(ack, 0, NULL);
	
}
Esempio n. 5
0
int w_acc_diam_request(struct sip_msg *rq, char *comment, char *foo)
{
	if (acc_preparse_req(rq)<0)
		return -1;
	env_set_to( rq->to );
	env_set_comment((struct acc_param*)comment);
	return acc_diam_request( rq, NULL);
}
Esempio n. 6
0
static int w_acc_db_request(struct sip_msg *rq, char *comment, char *table)
{
	str phrase;

	phrase.s=comment;
	phrase.len=strlen(comment);	/* fix_param would be faster! */
	acc_preparse_req(rq);
	return acc_db_request(rq, rq->to,&phrase,table, SQL_MC_FMT );
}
Esempio n. 7
0
int w_acc_log_request(struct sip_msg *rq, char *comment, char *foo)
{
	if (acc_preparse_req(rq)<0)
		return -1;
	env_set_to( rq->to );
	env_set_comment((struct acc_param*)comment);
	env_set_text( ACC_REQUEST, ACC_REQUEST_LEN);
	return acc_log_request( rq, NULL);
}
Esempio n. 8
0
static int w_acc_rad_request(struct sip_msg *rq, char *comment, 
				char *foo)
{
	str phrase;

	phrase.s=comment;
	phrase.len=strlen(comment);	/* fix_param would be faster! */
	acc_preparse_req(rq);
	return acc_rad_request(rq, rq->to,&phrase);
}
Esempio n. 9
0
int w_acc_diam_request(struct sip_msg *rq, char *comment, char *foo)
{
	struct acc_param *param = (struct acc_param*)comment;
	if (acc_preparse_req(rq)<0)
		return -1;
	if(acc_get_param_value(rq, param)<0)
		return -1;
	env_set_to( rq->to );
	env_set_comment(param);
	return acc_diam_request(rq);
}
Esempio n. 10
0
/* these wrappers parse all what may be needed; they don't care about
 * the result -- accounting functions just display "unavailable" if there
 * is nothing meaningful
 */
static int w_acc_log_request(struct sip_msg *rq, char *comment, char *foo)
{
	str txt; str phrase;

	txt.s=ACC_REQUEST;
	txt.len=ACC_REQUEST_LEN;
	phrase.s=comment;
	phrase.len=strlen(comment);	/* fix_param would be faster! */
	acc_preparse_req(rq);
	return acc_log_request(rq, rq->to, &txt, &phrase);
}
Esempio n. 11
0
int w_acc_aaa_request(struct sip_msg *rq, char *comment, char* foo)
{
	if (!aaa_proto_url) {
		LM_ERR("aaa support not configured\n");
		return -1;
	}
	if (acc_preparse_req(rq)<0)
		return -1;
	env_set_to( rq->to );
	env_set_comment((struct acc_param*)comment);
	return acc_aaa_request( rq, NULL);
}
Esempio n. 12
0
/* prepare message and transaction context for later accounting */
static void acc_onreq( struct cell* t, struct sip_msg *msg,
	int code, void *param )
{
	if (is_acc_on(msg) || is_mc_on(msg)) {
		acc_preparse_req(msg);
		/* also, if that is INVITE, disallow silent t-drop */
		if (msg->REQ_METHOD==METHOD_INVITE) {
			DBG("DEBUG: noisy_timer set for accounting\n");
			t->noisy_ctimer=1;
		}
	}
}
Esempio n. 13
0
int w_acc_diam_request(struct sip_msg *rq, pv_elem_t* comment, char *foo)
{
	struct acc_param accp;

	if (acc_preparse_req(rq)<0)
		return -1;

	acc_pvel_to_acc_param(rq, comment, &accp);

	env_set_to( rq->to );
	env_set_comment( &accp );
	return acc_diam_request( rq, NULL);
}
Esempio n. 14
0
/**
 * @brief execute an acc event via a specific engine
 */
int acc_api_exec(struct sip_msg *rq, acc_engine_t *eng,
		acc_param_t* comment)
{
	acc_info_t inf;
	if (acc_preparse_req(rq)<0)
		return -1;
	env_set_to(rq->to);
	env_set_comment(comment);
	memset(&inf, 0, sizeof(acc_info_t));
	inf.env  = &acc_env;
	acc_api_set_arrays(&inf);
	return eng->acc_req(rq, &inf);
}
Esempio n. 15
0
int w_acc_db_request(struct sip_msg *rq, char *comment, char *table)
{
	if (!table) {
		LM_ERR("db support not configured\n");
		return -1;
	}
	if (acc_preparse_req(rq)<0)
		return -1;
	env_set_to( rq->to );
	env_set_comment((struct acc_param*)comment);
	env_set_text(table, strlen(table));
	return acc_db_request( rq, NULL,NULL);
}
Esempio n. 16
0
int w_acc_log_request(struct sip_msg *rq, pv_elem_t* comment, char *foo)
{
	struct acc_param accp;

	if (acc_preparse_req(rq)<0)
		return -1;

	acc_pvel_to_acc_param(rq, comment, &accp);

	env_set_to( rq->to );
	env_set_comment( &accp );
	env_set_text( ACC_REQUEST, ACC_REQUEST_LEN);
	return acc_log_request( rq, NULL, 0);
}
Esempio n. 17
0
static void acc_onack( struct cell* t , struct sip_msg *ack,
	int code, void *param )
{
	/* only for those guys who insist on seeing ACKs as well */
	if (!report_ack) return;
	/* if acc enabled for flagged transaction, check if flag matches */
	if (is_log_acc_on(t->uas.request)) {
		acc_preparse_req(ack);
		acc_log_ack(t, ack);
	}
#ifdef SQL_ACC
	if (is_db_acc_on(t->uas.request)) {
		acc_preparse_req(ack);
		acc_db_ack(t, ack);
	}
#endif
#ifdef RAD_ACC
	if (is_rad_acc_on(t->uas.request)) {
		acc_preparse_req(ack);
		acc_rad_ack(t,ack);
	}
#endif
	
}
Esempio n. 18
0
/* prepare message and transaction context for later accounting */
void acc_onreq( struct cell* t, int type, struct tmcb_params *ps )
{
	int tmcb_types;
	int is_invite;
	int_str _avp_created_value;

	if ( ps->req && !skip_cancel(ps->req) &&
	(is_acc_on(ps->req) || is_mc_on(ps->req)) ) {
		/* do some parsing in advance */
		if (acc_preparse_req(ps->req)<0)
			return;
		is_invite = (ps->req->REQ_METHOD==METHOD_INVITE)?1:0;
		/* install additional handlers */
		tmcb_types =
			/* report on completed transactions */
			TMCB_RESPONSE_OUT |
			/* get incoming replies ready for processing */
			TMCB_RESPONSE_IN |
			/* report on missed calls */
			((is_invite && is_mc_on(ps->req))?TMCB_ON_FAILURE:0) ;

		/* if cdr accounting is enabled */
		if (is_cdr_acc_on(ps->req) && !has_totag(ps->req)) {
			_avp_created_value.n = time(NULL);

			if ( add_avp(0, acc_created_avp_id, _avp_created_value) != 0) {
				LM_ERR("failed to add created avp value!\n");
				return;
			}

			if (is_invite && create_acc_dlg(ps->req) < 0) {
				LM_ERR("cannot use dialog accounting module\n");
				return;
			}
		}
		if (tmb.register_tmcb( 0, t, tmcb_types, tmcb_func, 0, 0 )<=0) {
			LM_ERR("cannot register additional callbacks\n");
			return;
		}
		/* if required, determine request direction */
		if( detect_direction && !rrb.is_direction(ps->req,RR_FLOW_UPSTREAM) ) {
			LM_DBG("detected an UPSTREAM req -> flaging it\n");
			ps->req->msg_flags |= FL_REQ_UPSTREAM;
		}
	}
}
Esempio n. 19
0
int w_acc_aaa_request(struct sip_msg *rq, pv_elem_t* comment, char* foo)
{
	struct acc_param accp;

	if (!aaa_proto_url) {
		LM_ERR("aaa support not configured\n");
		return -1;
	}

	if (acc_preparse_req(rq)<0)
		return -1;

	acc_pvel_to_acc_param(rq, comment, &accp);

	env_set_to( rq->to );
	env_set_comment( &accp );
	return acc_aaa_request( rq, NULL, 0);
}
Esempio n. 20
0
int w_acc_db_request(struct sip_msg *rq, char *comment, char *table)
{
	struct acc_param *param = (struct acc_param*)comment;
	if (!table) {
		LM_ERR("db support not configured\n");
		return -1;
	}
	if (acc_preparse_req(rq)<0)
		return -1;
	if(acc_db_set_table_name(rq, (void*)table, NULL)<0) {
		LM_ERR("cannot set table name\n");
		return -1;
	}
	if(acc_get_param_value(rq, param)<0)
		return -1;
	env_set_to( rq->to );
	env_set_comment(param);
	return acc_db_request(rq);
}
Esempio n. 21
0
int w_do_acc_3(struct sip_msg* msg, char* type_p, char* flags_p, char* table_p)
{
	unsigned long long type=0, flags=0;
	unsigned long long flag_mask;

	acc_ctx_t* acc_ctx;

	acc_type_param_t* acc_param;

	str in;
	str table_name;

	int tmcb_types;
	int is_invite;

	if (type_p == NULL) {
		LM_ERR("accounting type is mandatory!\n");
		return -1;
	}

	acc_param = (acc_type_param_t *)type_p;
	if (acc_param->t == DO_ACC_PARAM_TYPE_VALUE) {
		type = acc_param->u.ival;
	} else {
		if (pv_printf_s(msg, acc_param->u.pval, &in) < 0) {
			LM_ERR("failed to fetch type value!\n");
			return -1;
		}

		if ((type=do_acc_parse(&in, do_acc_type_parser)) == DO_ACC_ERR) {
			LM_ERR("Invalid expression <%.*s> for acc type!\n", in.len, in.s);
			return -1;
		}
	}

	if (table_p != NULL) {
		if (fixup_get_svalue(msg, (gparam_p)table_p, &table_name) < 0) {
			LM_ERR("failed to fetch table name!\n");
			return -1;
		}
	}

	if (flags_p != NULL) {
		flags= *(unsigned long long*)flags_p;
	}

	flag_mask = type + type * flags;
	if (is_cdr_acc_on(flag_mask)) {
		/* setting this flag will allow us to register everything
		 * that is needed for CDR accounting only once */
		set_cdr_values_registered(flag_mask);
	}

	/* is it the first time when the function was called ? */
	acc_ctx = try_fetch_ctx();

	/* we go in here only if do_accounting function was called before;
	 * if accounting context is null or it's created but flags value is
	 * 0(meaning that context was created from somewhere else but do_accounting
	 * wasn't called)  then we need to jump over this and register
	 * all the callbacks we need */
	if (acc_ctx != NULL  && acc_ctx->flags != 0) {
		/* do_accounting already called once */
		/* first check if the accounting table changed  */
		if (is_db_acc_on(flag_mask) &&
				(table_p != NULL ||
				(acc_ctx->acc_table.s==NULL && acc_ctx->acc_table.len == 0))) {
			if (table_p == NULL) {
				table_name = db_table_acc;
			}

			if (store_acc_table( acc_ctx, &table_name) < 0) {
				LM_ERR("failed to store acc table!\n");
				return -1;
			}
		}

		if (!cdr_values_registered(acc_ctx->flags) &&
				cdr_values_registered(flag_mask)) {
			/* CDR support requested for the first time, we need to create
			 * the dialog support, if an initial INVITE */
			if (!has_totag(msg)) {
				acc_ctx->created = time(NULL);

				if (msg->REQ_METHOD == METHOD_INVITE && create_acc_dlg(msg) < 0) {
					LM_ERR("cannot use dialog accounting module\n");
					return -1;
				}
			}
		}

		/* if it's the first time the missed calls flag was used register the callback */
		if (is_mc_acc_on(flag_mask) && !failure_cb_registered(acc_ctx->flags)) {
			if (tmb.register_tmcb( msg, 0, TMCB_ON_FAILURE, tmcb_func, acc_ctx, 0)<=0) {
				LM_ERR("cannot register missed calls callback\n");
				return -1;
			}

			/* don't allow the callback to be registered agian in the future */
			set_failure_cb_registered(acc_ctx->flags);
		}

		acc_ctx->flags |= flag_mask;
		return 1;
	}

	/* initialize accounting context if not created before */
	if (acc_ctx == NULL && init_acc_ctx(&acc_ctx) < 0) {
		LM_ERR("failed to create accounting context!\n");
		return -1;
	}

	/* move acc table in context if we have database accounting */
	if (is_db_acc_on(flag_mask)) {
		if (table_p == NULL) {
			table_name = db_table_acc;
		}

		if (store_acc_table( acc_ctx, &table_name) < 0) {
			LM_ERR("failed to store acc table!\n");
			return -1;
		}
	}


	/*
	 * the first bit in each byte will just tell that we want that type of
	 * accounting
	 * next bits will tell extra options for that type of accounting
	 * so we keep the first bits in each byte and on the following positions
	 * next flags
	 */
	acc_ctx->flags = flag_mask;

	/* make sure that context won't be freed by GLOBAL_CONTEXT free function */
	acc_ctx->flags |= ACC_PROCESSING_CTX_NO_FREE;
	ACC_PUT_CTX(acc_ctx);

	if ( msg && !skip_cancel(msg) &&
	(is_acc_on(acc_ctx->flags) || is_mc_acc_on(acc_ctx->flags)) ) {
		/* do some parsing in advance */
		if (acc_preparse_req(msg)<0)
			return -1;
		is_invite = (msg->REQ_METHOD==METHOD_INVITE)?1:0;
		/* install additional handlers */
		tmcb_types =
			/* report on completed transactions */
			TMCB_RESPONSE_IN;

		if (is_invite && is_mc_acc_on(acc_ctx->flags)) {
			/* register it manually; see explanation below
			 * get incoming replies ready for processing */
			/* TMCB_RESPONSE_OUT | */
			/* report on missed calls */
			tmcb_types |= TMCB_ON_FAILURE;
			/* the flag will help on further do_accounting calls to know
			 * not to register the callback twice */
			set_failure_cb_registered(acc_ctx->flags);
		}

		/* if cdr accounting is enabled */
		if (is_cdr_acc_on(acc_ctx->flags) && !has_totag(msg)) {
			acc_ctx->created = time(NULL);

			if (is_invite && create_acc_dlg(msg) < 0) {
				LM_ERR("cannot use dialog accounting module\n");
				return -1;
			}
		}

		/* we do register_tmcb twice because we want to register the free
		 * function only once */
		if (tmb.register_tmcb( msg, 0, TMCB_RESPONSE_OUT, tmcb_func,
				acc_ctx, tm_free_acc_ctx)<=0) {
			LM_ERR("cannot register additional callbacks\n");
			return -1;
		}

		if (tmb.register_tmcb( msg, 0, tmcb_types, tmcb_func,
				acc_ctx, 0)<=0) {
			LM_ERR("cannot register additional callbacks\n");
			return -1;
		}

		/* if required, determine request direction */
		if( detect_direction && !rrb.is_direction(msg,RR_FLOW_UPSTREAM) ) {
			LM_DBG("detected an UPSTREAM req -> flaging it\n");
			msg->msg_flags |= FL_REQ_UPSTREAM;
		}
	}

	return 1;
}
Esempio n. 22
0
int w_do_acc_3(struct sip_msg* msg, char* type_p, char* flags_p, char* table_p)
{
	unsigned long long type=0, flags=0;
	unsigned long long *flag_mask_p, flag_mask;

	acc_type_param_t* acc_param;

	str in;
	str table_name;

	int tmcb_types;
	int is_invite;

	int_str _avp_created_value;

	if (type_p == NULL) {
		LM_ERR("accounting type is mandatory!\n");
		return -1;
	}

	acc_param = (acc_type_param_t *)type_p;
	if (acc_param->t == DO_ACC_PARAM_TYPE_VALUE) {
		type = acc_param->u.ival;
	} else {
		if (pv_printf_s(msg, acc_param->u.pval, &in) < 0) {
			LM_ERR("failed to fetch type value!\n");
			return -1;
		}

		if ((type=do_acc_parse(&in, do_acc_type_parser)) < 0) {
			LM_ERR("Invalid expression <%.*s> for acc type!\n", in.len, in.s);
			return -1;
		}
	}

	if (flags_p != NULL) {
		flags= *(unsigned long long*)flags_p;
	}

	flag_mask = type + type * flags;
	if (is_cdr_acc_on(flag_mask)) {
		/* setting this flag will allow us to register everything
		 * that is needed for CDR accounting only once */
		set_cdr_values_registered(flag_mask);
	}


	/* is it the first time when the function was called ? */
	if ((flag_mask_p=try_fetch_flags()) != NULL) {
		/* no the first time ; check now if CDRs are requested now
		 * for the first time */
		if (!cdr_values_registered(*flag_mask_p) &&
				cdr_values_registered(flag_mask)) {
			/* CDR support requested for the first time, we need to create
			 * the dialog support, if an initial INVITE */
			if (!has_totag(msg)) {
				_avp_created_value.n = time(NULL);

				if ( add_avp(0, acc_created_avp_id, _avp_created_value) != 0) {
					LM_ERR("failed to add created avp value!\n");
					return -1;
				}

				if (msg->REQ_METHOD == METHOD_INVITE && create_acc_dlg(msg) < 0) {
					LM_ERR("cannot use dialog accounting module\n");
					return -1;
				}
			}
		}

		*flag_mask_p |= flag_mask;
		return 1;
	}

	/* setting accouting for the first time, allocate the flags holder */
	flag_mask_p=shm_malloc(sizeof(unsigned long long));
	if (flag_mask_p==NULL) {
		LM_ERR("No more shm mem!\n");
		return -1;
	}


	/*
	 * the first bit in each byte will just tell that we want that type of
	 * accounting
	 * next bits will tell extra options for that type of accounting
	 * so we keep the first bits in each byte and on the following positions
	 * next flags
	 */
	*flag_mask_p = flag_mask;
	ACC_PUT_FLAGS(flag_mask_p);

	if (table_p != NULL) {
		if (fixup_get_svalue(msg, (gparam_p)table_p, &table_name) < 0) {
			LM_ERR("failed to fetch table name!\n");
			return -1;
		}
	}


	if ( msg && !skip_cancel(msg) &&
	(is_acc_on(*flag_mask_p) || is_mc_acc_on(*flag_mask_p)) ) {
		/* do some parsing in advance */
		if (acc_preparse_req(msg)<0)
			return -1;
		is_invite = (msg->REQ_METHOD==METHOD_INVITE)?1:0;
		/* install additional handlers */
		tmcb_types =
			/* report on completed transactions */
			TMCB_RESPONSE_IN |
			/* register it manually; see explanation below
			 * get incoming replies ready for processing */
			/* TMCB_RESPONSE_OUT | */
			/* report on missed calls */
			((is_invite && is_mc_acc_on(*flag_mask_p))?TMCB_ON_FAILURE:0) ;

		/* if cdr accounting is enabled */
		if (is_cdr_acc_on(*flag_mask_p) && !has_totag(msg)) {
			_avp_created_value.n = time(NULL);

			if ( add_avp(0, acc_created_avp_id, _avp_created_value) != 0) {
				LM_ERR("failed to add created avp value!\n");
				return -1;
			}

			if (is_invite && create_acc_dlg(msg) < 0) {
				LM_ERR("cannot use dialog accounting module\n");
				return -1;
			}
		}

		/* we do register_tmcb twice because we wan't to register the free
		 * fucntion only once */
		if (tmb.register_tmcb( msg, 0, TMCB_RESPONSE_OUT, tmcb_func,
				flag_mask_p, tm_free_acc_mask)<=0) {
			LM_ERR("cannot register additional callbacks\n");
			return -1;
		}

		if (tmb.register_tmcb( msg, 0, tmcb_types, tmcb_func,
				flag_mask_p, 0)<=0) {
			LM_ERR("cannot register additional callbacks\n");
			return -1;
		}

		/* if required, determine request direction */
		if( detect_direction && !rrb.is_direction(msg,RR_FLOW_UPSTREAM) ) {
			LM_DBG("detected an UPSTREAM req -> flaging it\n");
			msg->msg_flags |= FL_REQ_UPSTREAM;
		}
	}

	return 1;
}