int log_request(struct sip_msg *rq, str* ouri, struct hdr_field *to, char *table, unsigned int code, time_t req_timestamp)
{
	int cnt;
	if (skip_cancel(rq)) return 1;

        cnt = fmt2strar(log_fmt, rq, ouri, to, code, req_timestamp);
	if (cnt == 0) {
		LOG(L_ERR, "ERROR:acc:log_request: fmt2strar failed\n");
		return -1;
	}

	if (!db_url.len) {
		LOG(L_ERR, "ERROR:acc:log_request: can't log -- no db_url set\n");
		return -1;
	}

	if (acc_dbf.use_table(db_handle, table) < 0) {
		LOG(L_ERR, "ERROR:acc:log_request:Error in use_table\n");
		return -1;
	}

	if (acc_dbf.insert(db_handle, keys, vals, cnt) < 0) {
		LOG(L_ERR, "ERROR:acc:log_request:acc_request: Error while inserting to database\n");
		return -1;
	}

	return 1;
}
Beispiel #2
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;
		}
	}
}
Beispiel #3
0
/********************************************
 *        acc_request
 ********************************************/
int acc_log_request( struct sip_msg *rq, struct hdr_field *to, 
				str *txt, str *phrase)
{
	int len;
	char *log_msg;
	char *p;
	int attr_cnt;
	int attr_len;
	str* val_arr[ALL_LOG_FMT_LEN];
	str atr_arr[ALL_LOG_FMT_LEN];
	int i;

	if (skip_cancel(rq)) return 1;

	attr_cnt=fmt2strar( log_fmt, rq, to, phrase, 
					&len, &attr_len, val_arr, atr_arr);
	if (!attr_cnt) {
		LOG(L_ERR, "ERROR: acc_log_request: fmt2strar failed\n");
		return -1;
	}
	len+=attr_len+ACC_LEN+txt->len+A_EOL_LEN 
		+attr_cnt*(A_SEPARATOR_LEN+A_EQ_LEN)-A_SEPARATOR_LEN;
	log_msg=pkg_malloc(len);
	if (!log_msg) {
		LOG(L_ERR, "ERROR: acc_log_request: no mem\n");
		return -1;
	}

	/* skip leading text and begin with first item's
	 * separator ", " which will be overwritten by the
	 * leading text later 
	 * */
	p=log_msg+(ACC_LEN+txt->len-A_SEPARATOR_LEN);
	for (i=0; i<attr_cnt; i++) {
		memcpy(p, A_SEPARATOR, A_SEPARATOR_LEN );
		p+=A_SEPARATOR_LEN;
		memcpy(p, atr_arr[i].s, atr_arr[i].len);
		p+=atr_arr[i].len;
		memcpy(p, A_EQ, A_EQ_LEN);
		p+=A_EQ_LEN;
		memcpy(p, val_arr[i]->s, val_arr[i]->len);
		p+=val_arr[i]->len;
	}

	/* terminating text */
	memcpy(p, A_EOL, A_EOL_LEN); p+=A_EOL_LEN;
	/* leading text */
	p=log_msg;
	memcpy(p, ACC, ACC_LEN ); p+=ACC_LEN;
	memcpy(p, txt->s, txt->len); p+=txt->len;

	LOG(log_level, "%s", log_msg );

	pkg_free(log_msg);
	return 1;
}
Beispiel #4
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;
		}
	}
}
/* skip leading text and begin with first item's
 * separator ", " which will be overwritten by the
 * leading text later
 *
 */
static int log_request(struct sip_msg* rq, str* ouri, struct hdr_field* to, unsigned int code, time_t req_time)
{
	VALUE_PAIR *send;
	UINT4 av_type;

	send = NULL;
	if (skip_cancel(rq)) return 1;

	if (fmt2rad(log_fmt, rq, ouri, to, code, &send, req_time) < 0) goto error;

	     /* Add Acct-Status-Type attribute */
	av_type = rad_status(rq, code);
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_ACCT_STATUS_TYPE].v), &av_type, -1, 
			   VENDOR(attrs[A_ACCT_STATUS_TYPE].v))) {
		ERR("Add Status-Type\n");
		goto error;
	}

	     /* Add Service-Type attribute */
	av_type = (service_type != -1) ? service_type : vals[V_SIP_SESSION].v;
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SERVICE_TYPE].v), &av_type, -1, 
			   VENDOR(attrs[A_SERVICE_TYPE].v))) {
		ERR("add STATUS_TYPE\n");
		goto error;
	}

	     /* Add User-Name attribute */
	if (add_user_name(rq, rh, &send) < 0) goto error;

	     /* Send the request out */
	if (rc_acct(rh, SIP_PORT, send) != OK_RC) {
		ERR("RADIUS accounting request failed\n");
		goto error;
	}

	rc_avpair_free(send);
	return 1;

error:
	rc_avpair_free(send);
	return -1;
}
/* is this reply of interest for accounting ? */
static inline int should_acc_reply(struct cell* t, int code)
{
	struct sip_msg *r;

	r = t->uas.request;

	     /* validation */
	if (r == 0) {
		LOG(L_ERR, "ERROR:acc:should_acc_reply: 0 request\n");
		return 0;
	}

	     /* negative transactions reported otherwise only if explicitly
	      * demanded */
	if (!failed_transactions && code >= 300) return 0;
	if (!is_acc_on(r)) return 0;
	if (skip_cancel(r)) return 0;
	if (code < 200 && ! (early_media && code == 183)) return 0;
	return 1; /* seed is through, we will account this reply */
}
Beispiel #7
0
int log_request(struct sip_msg *rq, str* ouri, struct hdr_field *to, db_cmd_t* cmd, unsigned int code, time_t req_timestamp)
{
	int cnt;
	if (skip_cancel(rq)) return 1;

	cnt = fmt2strar(log_fmt, rq, ouri, to, code, req_timestamp, cmd->vals);
	if (cnt == 0) {
		LOG(L_ERR, "ERROR:acc:log_request: fmt2strar failed\n");
		return -1;
	}

	if (!db_url.len) {
		LOG(L_ERR, "ERROR:acc:log_request: can't log -- no db_url set\n");
		return -1;
	}

	if (db_exec(NULL, cmd) < 0) {
		ERR("Error while inserting to database\n");
		return -1;
	}

	return 1;
}
Beispiel #8
0
int acc_diam_request( struct sip_msg *rq, struct hdr_field *to, str *phrase )
{
	str* val_arr[ALL_LOG_FMT_LEN+1];
	str atr_arr[ALL_LOG_FMT_LEN+1];
	int attr_cnt;
	AAAMessage *send = NULL;
	AAA_AVP *avp;
	int i;
	int dummy_len;
	str* user;
	str* realm;
	str user_name;
	str value;
	str *uri;
	struct sip_uri puri;
	struct to_body* from;
	int ret, free_user_name;
	int status;
	char tmp[2];
	unsigned int mid;


	if (skip_cancel(rq)) return 1;

	attr_cnt=fmt2strar( DIAM_ACC_FMT, rq, to, phrase, 
					&dummy_len, &dummy_len, val_arr, atr_arr);
	
	if (attr_cnt!=(sizeof(DIAM_ACC_FMT)-1)) 
	{
		LOG(L_ERR, "ERROR: acc_diam_request: fmt2strar failed\n");
		return -1;
	}
	
	if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL)
	{
		LOG(L_ERR, "ERROR: acc_diam_request: new AAA message not created\n");
		return -1;
	}


	/* AVP_ACCOUNTIG_RECORD_TYPE */
	if( (status = diam_status(rq, phrase))<0)
	{
		LOG(L_ERR, "ERROR: acc_diam_request: status unknown\n");
		goto error;
	}
	tmp[0] = status+'0';
	tmp[1] = 0;
	if( (avp=AAACreateAVP(AVP_Accounting_Record_Type, 0, 0, tmp, 
						1, AVP_DUPLICATE_DATA)) == 0)
	{
		LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}
	/* SIP_MSGID AVP */
	DBG("**ACC***** m_id=%d\n", rq->id);
	mid = rq->id;
	if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid), 
				sizeof(mid), AVP_DUPLICATE_DATA)) == 0)
	{
		LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}

	/* SIP Service AVP */
	if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_ACCOUNTING, 
				SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0)
	{
		LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}

	/* SIP_STATUS avp */
	if( (avp=AAACreateAVP(AVP_SIP_STATUS, 0, 0, phrase->s, 
						phrase->len, AVP_DUPLICATE_DATA)) == 0)
	{
		LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}

	/* SIP_METHOD avp */
	value = rq->first_line.u.request.method;
	if( (avp=AAACreateAVP(AVP_SIP_METHOD, 0, 0, value.s, 
						value.len, AVP_DUPLICATE_DATA)) == 0)
	{
		LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}

	/* Handle AVP_USER_NAME as a special case */
	free_user_name = 0;
	user=cred_user(rq);  /* try to take it from credentials */
	if (user) 
	{
		realm = cred_realm(rq);
		if (realm) 
		{
			user_name.len = user->len+1+realm->len;
			user_name.s = pkg_malloc(user_name.len);
			if (!user_name.s) 
			{
				LOG(L_ERR, "ERROR: acc_diam_request: no memory\n");
				goto error;
			}
			memcpy(user_name.s, user->s, user->len);
			user_name.s[user->len] = '@';
			memcpy(user_name.s+user->len+1, realm->s, realm->len);
			free_user_name = 1;
		} 
		else 
		{
			user_name.len = user->len;
			user_name.s = user->s;
		}
	} 
	else 
	{  /* from from uri */
		if (rq->from && (from=get_from(rq)) && from->uri.len) 
		{
			if (parse_uri(from->uri.s, from->uri.len, &puri) < 0 ) 
			{
				LOG(L_ERR, "ERROR: acc_diam_request: Bad From URI\n");
				goto error;
			}
			user_name.len = puri.user.len+1+puri.host.len;
			user_name.s = pkg_malloc(user_name.len);
			if (!user_name.s) {
				LOG(L_ERR, "ERROR: acc_diam_request: no memory\n");
				goto error;
			}
			memcpy(user_name.s, puri.user.s, puri.user.len);
			user_name.s[puri.user.len] = '@';
			memcpy(user_name.s+puri.user.len+1, puri.host.s, puri.host.len);
			free_user_name = 1;
		} 
		else 
		{
			user_name.len = na.len;
			user_name.s = na.s;
		}
	}

	if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, 
					free_user_name?AVP_FREE_DATA:AVP_DUPLICATE_DATA)) == 0)
	{
		LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n");
		if(free_user_name)
			pkg_free(user_name.s);
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}

	
    /* Remaining attributes from diam_attr vector */
	for(i=0; i<attr_cnt; i++) 
	{
		if((avp=AAACreateAVP(diam_attr[i], 0,0, val_arr[i]->s, val_arr[i]->len, 
					AVP_DUPLICATE_DATA)) == 0)
		{
			LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n");
			goto error;
		}
		if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS)
		{
			LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n");
			AAAFreeAVP(&avp);
			goto error;
		}
	}
		
	if (get_uri(rq, &uri) < 0) 
	{
		LOG(L_ERR, "ERROR: acc_diam_request: From/To URI not found\n");
		goto error;
	}
	
	if (parse_uri(uri->s, uri->len, &puri) < 0) 
	{
		LOG(L_ERR, "ERROR: acc_diam_request: Error parsing From/To URI\n");
		goto error;
	}

	
	/* Destination-Realm AVP */
	if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s,
						puri.host.len, AVP_DUPLICATE_DATA)) == 0)
	{
		LOG(L_ERR,"acc_diam_request: no more free memory!\n");
		goto error;
	}

	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LOG(L_ERR, "acc_diam_request: avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}


	/* prepare the message to be sent over the network */
	if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS)
	{
		LOG(L_ERR, "ERROR: acc_diam_request: message buffer not created\n");
		goto error;
	}

	if(sockfd==AAA_NO_CONNECTION)
	{
		sockfd = init_mytcp(diameter_client_host, diameter_client_port);
		if(sockfd==AAA_NO_CONNECTION)
		{
			LOG(L_ERR, M_NAME":acc_diam_request: failed to reconnect"
								" to Diameter client\n");
			goto error;
		}
	}
		
	/* send the message to the DIAMETER client */
	ret = tcp_send_recv(sockfd, send->buf.s, send->buf.len, rb, rq->id);

	if(ret == AAA_CONN_CLOSED)
	{
		LOG(L_NOTICE, M_NAME":acc_diam_request: connection to Diameter"
					" client closed.It will be reopened by the next request\n");
		close(sockfd);
		sockfd = AAA_NO_CONNECTION;
		goto error;
	}

	if(ret != ACC_SUCCESS) /* a transmission error occurred */
	{
		LOG(L_ERR, M_NAME":acc_diam_request: message sending to the" 
					" DIAMETER backend authorization server failed\n");
		goto error;
	}

	AAAFreeMessage(&send);
	return 1;

error:
	AAAFreeMessage(&send);
	return -1;
}
Beispiel #9
0
int acc_rad_request( struct sip_msg *rq, struct hdr_field *to, 
		     str *phrase )
{
	str* val_arr[ALL_LOG_FMT_LEN+1];
	str atr_arr[ALL_LOG_FMT_LEN+1];
	int attr_cnt;
	VALUE_PAIR *send;
	UINT4 av_type;
	int i;
	int dummy_len;
	str* user;
	str* realm;
	str user_name;
	struct sip_uri puri;
	struct to_body* from;
#ifdef _OBSO
	char nullcode="00000";
	char ccode[6];
	char *c;
#endif

	send=NULL;

	if (skip_cancel(rq)) return 1;

	attr_cnt=fmt2strar( RAD_ACC_FMT, rq, to, phrase, 
					&dummy_len, &dummy_len, val_arr, atr_arr);
	if (attr_cnt!=(sizeof(RAD_ACC_FMT)-1)) {
		LOG(L_ERR, "ERROR: acc_rad_request: fmt2strar failed\n");
		goto error;
	}

	av_type=rad_status(rq, phrase);
	if (!rc_avpair_add(rh, &send, attrs[A_ACCT_STATUS_TYPE].v, &av_type, -1, 0)) {
		LOG(L_ERR, "ERROR: acc_rad_request: add STATUS_TYPE\n");
		goto error;
	}
	av_type=vals[V_SIP_SESSION].v;
	if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &av_type, -1, 0)) {
		LOG(L_ERR, "ERROR: acc_rad_request: add STATUS_TYPE\n");
		goto error;
	}
	av_type=phrase2code(phrase); /* status=integer */
	/* if (phrase.len<3) c=nullcode;
	else { memcpy(ccode, phrase.s, 3); ccode[3]=0;c=nullcode;} */
	if (!rc_avpair_add(rh, &send, attrs[A_SIP_RESPONSE_CODE].v, &av_type, -1, 0)) {
		LOG(L_ERR, "ERROR: acc_rad_request: add RESPONSE_CODE\n");
		goto error;
	}
	av_type=rq->REQ_METHOD;
	if (!rc_avpair_add(rh, &send, attrs[A_SIP_METHOD].v, &av_type, -1, 0)) {
		LOG(L_ERR, "ERROR: acc_rad_request: add SIP_METHOD\n");
		goto error;
	}
        /* Handle User-Name as a special case */
	user=cred_user(rq);  /* try to take it from credentials */
	if (user) {
		realm = cred_realm(rq);
		if (realm) {
			user_name.len = user->len+1+realm->len;
			user_name.s = pkg_malloc(user_name.len);
			if (!user_name.s) {
				LOG(L_ERR, "ERROR: acc_rad_request: no memory\n");
				goto error;
			}
			memcpy(user_name.s, user->s, user->len);
			user_name.s[user->len] = '@';
			memcpy(user_name.s+user->len+1, realm->s, realm->len);
			if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, 
					   user_name.s, user_name.len, 0)) {
				LOG(L_ERR, "ERROR: acc_rad_request: rc_avpaid_add "
				    "failed for %d\n", attrs[A_USER_NAME].v );
				pkg_free(user_name.s);
				goto error;
			}
			pkg_free(user_name.s);
		} else {
			user_name.len = user->len;
			user_name.s = user->s;
			if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, 
					   user_name.s, user_name.len, 0)) {
				LOG(L_ERR, "ERROR: acc_rad_request: rc_avpaid_add "
				    "failed for %d\n", attrs[A_USER_NAME].v );
				goto error;
			}
		}
	} else {  /* from from uri */
		if (rq->from && (from=get_from(rq)) && from->uri.len) {
			if (parse_uri(from->uri.s, from->uri.len, &puri) < 0 ) {
				LOG(L_ERR, "ERROR: acc_rad_request: Bad From URI\n");
				goto error;
			}
			user_name.len = puri.user.len+1+puri.host.len;
			user_name.s = pkg_malloc(user_name.len);
			if (!user_name.s) {
				LOG(L_ERR, "ERROR: acc_rad_request: no memory\n");
				goto error;
			}
			memcpy(user_name.s, puri.user.s, puri.user.len);
			user_name.s[puri.user.len] = '@';
			memcpy(user_name.s+puri.user.len+1, puri.host.s, puri.host.len);
			if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, 
					   user_name.s, user_name.len, 0)) {
				LOG(L_ERR, "ERROR: acc_rad_request: rc_avpaid_add "
				    "failed for %d\n", attrs[A_USER_NAME].v );
				pkg_free(user_name.s);
				goto error;
			}
			pkg_free(user_name.s);
		} else {
			user_name.len = na.len;
			user_name.s = na.s;
			if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, 
					   user_name.s, user_name.len, 0)) {
				LOG(L_ERR, "ERROR: acc_rad_request: rc_avpaid_add "
				    "failed for %d\n", attrs[A_USER_NAME].v );
				goto error;
			}
		}
	}
        /* Remaining attributes from rad_attr vector */
	for(i=0; i<attr_cnt; i++) {
		if (!rc_avpair_add(rh, &send, attrs[rad_attr[i]].v, 
				   val_arr[i]->s,val_arr[i]->len, 0)) {
			LOG(L_ERR, "ERROR: acc_rad_request: rc_avpaid_add "
			    "failed for %s\n", attrs[rad_attr[i]].n );
			goto error;
		}
	}
		
	if (rc_acct(rh, SIP_PORT, send)!=OK_RC) {
		LOG(L_ERR, "ERROR: acc_rad_request: radius-ing failed\n");
		goto error;
	}
	rc_avpair_free(send);
	return 1;

error:
	rc_avpair_free(send);
	return -1;
}
Beispiel #10
0
int acc_db_request( struct sip_msg *rq, struct hdr_field *to, 
				str *phrase, char *table, char *fmt)
{
	db_val_t vals[ALL_LOG_FMT_LEN+1];
	str* val_arr[ALL_LOG_FMT_LEN+1];
	str atr_arr[ALL_LOG_FMT_LEN+1];
	/* caution: keys need to be aligned to formatting strings */
	db_key_t keys[] = {acc_from_uri, acc_to_uri,
		acc_sip_method_col, acc_i_uri_col, 
		acc_o_uri_col, acc_sip_from_col, acc_sip_callid_col,
   		acc_sip_to_col, acc_sip_status_col, acc_user_col, 
		acc_totag_col, acc_fromtag_col, acc_domain_col, acc_time_col };

	struct tm *tm;
	time_t timep;
	char time_s[20];
	int attr_cnt;

	int i;
	int dummy_len;

	if (skip_cancel(rq)) return 1;

	/* database columns:
	 * "sip_method", "i_uri", "o_uri", "sip_from", "sip_callid", 
	 * "sip_to", "sip_status", "user", "time"
	 */
	attr_cnt=fmt2strar( fmt, rq, to, phrase, 
					&dummy_len, &dummy_len, val_arr, atr_arr);
	if (!attr_cnt) {
		LOG(L_ERR, "ERROR: acc_db_request: fmt2strar failed\n");
		return -1;
	}

	if (!acc_db_url) {
		LOG(L_ERR, "ERROR: can't log -- no db_url set\n");
		return -1;
	}

	timep = time(NULL);
	tm = db_localtime ? localtime(&timep) : gmtime(&timep);
	strftime(time_s, 20, "%Y-%m-%d %H:%M:%S", tm);


	for(i=0; i<attr_cnt; i++) {
		VAL_TYPE(vals+i)=DB_STR;
		VAL_NULL(vals+i)=0;
		VAL_STR(vals+i)=*val_arr[i];
	}
	/* time */
	VAL_TYPE(vals+i)=DB_STRING;
	VAL_NULL(vals+i)=0;
	VAL_STRING(vals+i)=time_s;

	if (acc_dbf.use_table(db_handle, table) < 0) {
		LOG(L_ERR, "ERROR: acc_request: "
		           "Error in use_table\n");
		return -1;
	}
	
	if (acc_dbf.insert(db_handle, keys, vals, i+1) < 0) {
		LOG(L_ERR, "ERROR: acc_request: "
				"Error while inserting to database\n");
		return -1;
	}

	return 1;
}
Beispiel #11
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;
}
Beispiel #12
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;
}