Beispiel #1
0
int acc_log_request( struct sip_msg *rq)
{
	static char log_msg[MAX_SYSLOG_SIZE];
	static char *log_msg_end=log_msg+MAX_SYSLOG_SIZE-2;
	char *p;
	int n;
	int m;
	int i;

	/* get default values */
	m = core2strar( rq, val_arr, int_arr, type_arr);

	/* get extra values */
	m += extra2strar( log_extra, rq, val_arr+m, int_arr+m, type_arr+m);

	for ( i=0,p=log_msg ; i<m ; i++ ) {
		if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) {
			LM_WARN("acc message too long, truncating..\n");
			p = log_msg_end;
			break;
		}
		*(p++) = A_SEPARATOR_CHR;
		memcpy(p, log_attrs[i].s, log_attrs[i].len);
		p += log_attrs[i].len;
		*(p++) = A_EQ_CHR;
		memcpy(p, val_arr[i].s, val_arr[i].len);
		p += val_arr[i].len;
	}

	/* get per leg attributes */
	if ( leg_info ) {
	        n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m, 1);
		do {
			for (i=m; i<m+n; i++) {
				if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) {
					LM_WARN("acc message too long, truncating..\n");
					p = log_msg_end;
					break;
				}
				*(p++) = A_SEPARATOR_CHR;
				memcpy(p, log_attrs[i].s, log_attrs[i].len);
				p += log_attrs[i].len;
				*(p++) = A_EQ_CHR;
				memcpy(p, val_arr[i].s, val_arr[i].len);
				p += val_arr[i].len;
			}
		}while (p!=log_msg_end && (n=legs2strar(leg_info,rq,val_arr+m,
							int_arr+m,type_arr+m,
							0))!=0);
	}

	/* terminating line */
	*(p++) = '\n';
	*(p++) = 0;

	LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu%s",
		acc_env.text.len, acc_env.text.s,(unsigned long) acc_env.ts, log_msg);

	return 1;
}
Beispiel #2
0
/* gets extra values from dlg and stores them into val_arr array */
static int prebuild_extra_arr(struct dlg_cell *dlg, struct sip_msg *msg,
		str *buffer, str *type_str, struct acc_extra * extra, int start)
{
	short extra_len;

	if (!start || !type_str || !buffer) {
		LM_ERR("invalid parameters\n");
		return -1;
	}
	buffer->len = 0;
	buffer->s = 0;

	/* fetching extra string values */
	if (dlg_api.fetch_dlg_value(dlg, type_str, buffer, 1) < 0) {
		LM_ERR("cannot fetch core string value\n");
		return -1;
	}

	extra_len = GET_LEN(buffer->s);
	buffer->len = 2;
	complete_dlg_values(buffer, val_arr + start, extra_len);
	start += extra_len;

	/* populate the extra from bye */
	return  start + extra2strar(extra, msg, NULL, val_arr + start, 1);
}
Beispiel #3
0
int acc_db_request( struct sip_msg *rq, struct sip_msg *rpl,
		query_list_t **ins_list)
{
	static db_ps_t my_ps_ins = NULL;
	static db_ps_t my_ps = NULL;
	int m;
	int n;
	int i;

	/* formated database columns */
	m = core2strar( rq, val_arr );

	for(i = 0; i < m; i++)
		VAL_STR(db_vals+i) = val_arr[i];
	/* time value */
	VAL_TIME(db_vals+(m++)) = acc_env.ts;

	/* extra columns */
	m += extra2strar( db_extra, rq, rpl, val_arr+m, 0);

	for( i++; i < m; i++)
		VAL_STR(db_vals+i) = val_arr[i];

	acc_dbf.use_table(db_handle, &acc_env.text/*table*/);
	CON_PS_REFERENCE(db_handle) = ins_list? &my_ps_ins : &my_ps;

	/* multi-leg columns */
	if ( !leg_info ) {
		if (con_set_inslist(&acc_dbf,db_handle,ins_list,db_keys,m) < 0 )
			CON_RESET_INSLIST(db_handle);
		if (acc_dbf.insert(db_handle, db_keys, db_vals, m) < 0) {
			LM_ERR("failed to insert into database\n");
			return -1;
		}
	} else {
		n = legs2strar(leg_info,rq,val_arr+m,1);
		do {
			for ( i = m; i < m + n; i++)
				VAL_STR(db_vals+i)=val_arr[i];
			if (con_set_inslist(&acc_dbf,db_handle,ins_list,db_keys,m+n) < 0 )
				CON_RESET_INSLIST(db_handle);
			if (acc_dbf.insert(db_handle, db_keys, db_vals, m+n) < 0) {
				LM_ERR("failed to insert into database\n");
				return -1;
			}
		}while ( (n = legs2strar(leg_info,rq,val_arr+m,0))!=0 );
	}

	return 1;
}
Beispiel #4
0
/* builds extra values string */
static int build_extra_dlg_values(struct acc_extra *extra,
		struct dlg_cell *dlg,struct sip_msg *req, struct sip_msg *reply)
{
	str val_arr[MAX_ACC_EXTRA];
	int nr, i;

	cdr_buf.len = 2;
	nr = extra2strar(extra, req, reply, val_arr, 0);

	for (i=0; i<nr; i++)
		if (set_dlg_value(&val_arr[i]) < 0)
			return -1;
	SET_LEN(cdr_buf.s, nr);
	return nr;
}
Beispiel #5
0
int acc_db_request( struct sip_msg *rq)
{
	int m;
	int n;
	int i;

	/* formated database columns */
	m = core2strar( rq, val_arr, int_arr, type_arr );

	for(i=0; i<m; i++)
		VAL_STR(db_vals+i) = val_arr[i];
	/* time value */
	VAL_TIME(db_vals+(m++)) = acc_env.ts;

	/* extra columns */
	m += extra2strar( db_extra, rq, val_arr+m, int_arr+m, type_arr+m);

	for( i++ ; i<m; i++)
		VAL_STR(db_vals+i) = val_arr[i];

	if (acc_dbf.use_table(db_handle, &acc_env.text/*table*/) < 0) {
		LM_ERR("error in use_table\n");
		return -1;
	}

	/* multi-leg columns */
	if ( !leg_info ) {
		if (acc_dbf.insert(db_handle, db_keys, db_vals, m) < 0) {
			LM_ERR("failed to insert into database\n");
			return -1;
		}
	} else {
  	        n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m,1);
		do {
			for (i=m; i<m+n; i++)
				VAL_STR(db_vals+i)=val_arr[i];
			if (acc_dbf.insert(db_handle, db_keys, db_vals, m+n) < 0) {
				LM_ERR("failed to insert into database\n");
				return -1;
			}
		}while ( (n=legs2strar(leg_info,rq,val_arr+m,int_arr+m,
				       type_arr+m,0))!=0 );
	}

	return 1;
}
Beispiel #6
0
/* collect all crd data and write it to a syslog */
static int log_write_cdr( struct dlg_cell* dialog,
                      struct sip_msg* message)
{
    static char cdr_message[ MAX_SYSLOG_SIZE];
    static char* const cdr_message_end = cdr_message +
                                         MAX_SYSLOG_SIZE -
                                         2;// -2 because of the string ending '\n\0'
    char* message_position = NULL;
    int message_index = 0;
    int counter = 0;

	if(cdr_log_enable==0)
		return 0;

    /* get default values */
    message_index = cdr_core2strar( dialog,
                                    cdr_value_array,
                                    cdr_int_array,
                                    cdr_type_array);

    /* get extra values */
    message_index += extra2strar( cdr_extra,
                                  message,
                                  cdr_value_array + message_index,
                                  cdr_int_array + message_index,
                                  cdr_type_array + message_index);

    for( counter = 0, message_position = cdr_message;
         counter < message_index ;
         counter++ )
    {
        const char* const next_message_end = message_position +
                                             2 + // ', ' -> two letters
                                             cdr_attrs[ counter].len +
                                             1 + // '=' -> one letter
                                             cdr_value_array[ counter].len;

        if( next_message_end >= cdr_message_end ||
            next_message_end < message_position)
        {
            LM_WARN("cdr message too long, truncating..\n");
            message_position = cdr_message_end;
            break;
        }

        if( counter > 0)
        {
            *(message_position++) = A_SEPARATOR_CHR;
            *(message_position++) = A_SEPARATOR_CHR_2;
        }

        memcpy( message_position,
                cdr_attrs[ counter].s,
                cdr_attrs[ counter].len);

        message_position += cdr_attrs[ counter].len;

        *( message_position++) = A_EQ_CHR;

        memcpy( message_position,
                cdr_value_array[ counter].s,
                cdr_value_array[ counter].len);

        message_position += cdr_value_array[ counter].len;
    }

    /* terminating line */
    *(message_position++) = '\n';
    *(message_position++) = '\0';

    LM_GEN2( cdr_facility, log_level, "%s", cdr_message);

    return 0;
}
Beispiel #7
0
/* collect all crd data and write it to a syslog */
static int db_write_cdr( struct dlg_cell* dialog,
                      struct sip_msg* message)
{
	int m = 0;
	int i;
	db_func_t *df=NULL;
	db1_con_t *dh=NULL;
	void *vf=NULL;
	void *vh=NULL;

	if(acc_cdrs_table.len<=0)
		return 0;

	if(acc_get_db_handlers(&vf, &vh)<0) {
		LM_ERR("cannot get db handlers\n");
		return -1;
	}
	df = (db_func_t*)vf;
	dh = (db1_con_t*)vh;

	/* get default values */
	m = cdr_core2strar( dialog,
						cdr_value_array,
						cdr_int_array,
						cdr_type_array);

	for(i=0; i<m; i++) {
		db_cdr_keys[i] = &cdr_attrs[i];
		VAL_TYPE(db_cdr_vals+i)=DB1_STR;
		VAL_NULL(db_cdr_vals+i)=0;
		VAL_STR(db_cdr_vals+i) = cdr_value_array[i];
	}

    /* get extra values */
	m += extra2strar( cdr_extra,
						message,
						cdr_value_array + m,
						cdr_int_array + m,
						cdr_type_array + m);
	for( ; i<m; i++) {
		db_cdr_keys[i] = &cdr_attrs[i];
		VAL_TYPE(db_cdr_vals+i)=DB1_STR;
		VAL_NULL(db_cdr_vals+i)=0;
		VAL_STR(db_cdr_vals+i) = cdr_value_array[i];
	}

	if (df->use_table(dh, &acc_cdrs_table /*table*/) < 0) {
		LM_ERR("error in use_table\n");
		return -1;
	}

	if(acc_db_insert_mode==1 && df->insert_delayed!=NULL) {
		if (df->insert_delayed(dh, db_cdr_keys, db_cdr_vals, m) < 0) {
			LM_ERR("failed to insert delayed into database\n");
			return -1;
		}
	} else {
		if (df->insert(dh, db_cdr_keys, db_cdr_vals, m) < 0) {
			LM_ERR("failed to insert into database\n");
			return -1;
		}
	}

	return 0;
}
Beispiel #8
0
/* collect all crd data and write it to a syslog */
static int log_write_cdr( struct dlg_cell* dialog,
                      struct sip_msg* message)
{
    static char cdr_message[ MAX_SYSLOG_SIZE];
    static char* const cdr_message_end = cdr_message +
                                         MAX_SYSLOG_SIZE -
                                         2;// -2 because of the string ending '\n\0'
    char* message_position = NULL;
    int message_index = 0;
	int extra_index = 0;
    int counter = 0;

	if(cdr_log_enable==0)
		return 0;

    /* get default values */
    message_index = cdr_core2strar( dialog,
                                    cdr_value_array,
                                    cdr_int_array,
                                    cdr_type_array);

    /* get extra values */
    if (message)
    {
        extra_index += extra2strar( cdr_extra,
                                      message,
                                      cdr_value_array + message_index,
                                      cdr_int_array + message_index,
                                      cdr_type_array + message_index);
    } else if (cdr_expired_dlg_enable){
        LM_DBG("fallback to dlg_only search because of message does not exist.\n");
        message_index += extra2strar_dlg_only( cdr_extra,
                                               dialog,
                                               cdr_value_array + message_index,
                                               cdr_int_array + message_index,
                                               cdr_type_array + message_index,
                                               &dlgb);
    }
	message_index += extra_index;

    for( counter = 0, message_position = cdr_message;
         counter < message_index ;
         counter++ )
    {
        const char* const next_message_end = message_position +
                                             2 + // ', ' -> two letters
                                             cdr_attrs[ counter].len +
                                             1 + // '=' -> one letter
                                             cdr_value_array[ counter].len;

        if( next_message_end >= cdr_message_end ||
            next_message_end < message_position)
        {
            LM_WARN("cdr message too long, truncating..\n");
            message_position = cdr_message_end;
            break;
        }

        if( counter > 0)
        {
            *(message_position++) = A_SEPARATOR_CHR;
            *(message_position++) = A_SEPARATOR_CHR_2;
        }

        memcpy( message_position,
                cdr_attrs[ counter].s,
                cdr_attrs[ counter].len);

        message_position += cdr_attrs[ counter].len;

        *( message_position++) = A_EQ_CHR;

        memcpy( message_position,
                cdr_value_array[ counter].s,
                cdr_value_array[ counter].len);

        message_position += cdr_value_array[ counter].len;
    }

    /* terminating line */
    *(message_position++) = '\n';
    *(message_position++) = '\0';

    LM_GEN2( cdr_facility, log_level, "%s", cdr_message);

	/* free memory allocated by extra2strar, nothing is done in case no extra strings were found by extra2strar */
    free_strar_mem( &(cdr_type_array[message_index-extra_index]), &(cdr_value_array[message_index-extra_index]),
				   extra_index, message_index);
    return 0;
}
Beispiel #9
0
/* collect all crd data and write it to a syslog */
static int db_write_cdr( struct dlg_cell* dialog,
                      struct sip_msg* message)
{
	int m = 0;
	int n = 0;
	int i;
	db_func_t *df=NULL;
	db1_con_t *dh=NULL;
	void *vf=NULL;
	void *vh=NULL;
	struct timeval timeval_val;
	long long_val;
	double double_val;
	char * end;

	if(acc_cdrs_table.len<=0)
		return 0;

	if(acc_get_db_handlers(&vf, &vh)<0) {
		LM_ERR("cannot get db handlers\n");
		return -1;
	}
	df = (db_func_t*)vf;
	dh = (db1_con_t*)vh;

	/* get default values */
	m = cdr_core2strar( dialog,
						cdr_value_array,
						cdr_int_array,
						cdr_type_array);

	for(i=0; i<m; i++) {
		db_cdr_keys[i] = &cdr_attrs[i];
		/* reset errno, some strtoX don't reset it */
		errno = 0;
		switch(cdr_type_array[i]) {
			case TYPE_NULL:
				VAL_NULL(db_cdr_vals+i)=1;
				break;
			case TYPE_INT:
				VAL_TYPE(db_cdr_vals+i)=DB1_INT;
				VAL_NULL(db_cdr_vals+i)=0;
				long_val = strtol(cdr_value_array[i].s, &end, 10);
				if(errno && (errno != EAGAIN)) {
					LM_ERR("failed to convert string to integer - %d.\n", errno);
					goto error;
				}
				VAL_INT(db_cdr_vals+i) = long_val;
				break;
			case TYPE_STR:
				VAL_TYPE(db_cdr_vals+i)=DB1_STR;
				VAL_NULL(db_cdr_vals+i)=0;
				VAL_STR(db_cdr_vals+i) = cdr_value_array[i];
				break;
			case TYPE_DATE:
				VAL_TYPE(db_cdr_vals+i)=DB1_DATETIME;
				VAL_NULL(db_cdr_vals+i)=0;
				if(string2time(&cdr_value_array[i], &timeval_val) < 0) {
					LM_ERR("failed to convert string to timeval.\n");
					goto error;
				}
				VAL_TIME(db_cdr_vals+i) = timeval_val.tv_sec;
				break;
			case TYPE_DOUBLE:
				VAL_TYPE(db_cdr_vals+i)=DB1_DOUBLE;
				VAL_NULL(db_cdr_vals+i)=0;
				double_val = strtod(cdr_value_array[i].s, &end);
				if(errno && (errno != EAGAIN)) {
					LM_ERR("failed to convert string to double - %d.\n", errno);
					goto error;
				}
				VAL_DOUBLE(db_cdr_vals+i) = double_val;
				break;
		}
	}

    /* get extra values */
    if (message)
    {
		n += extra2strar( cdr_extra,
							message,
							cdr_value_array + m,
							cdr_int_array + m,
							cdr_type_array + m);
		m += n;
    } else if (cdr_expired_dlg_enable){
        LM_WARN( "fallback to dlg_only search because of message doesn't exist.\n");
        m += extra2strar_dlg_only( cdr_extra,
                dialog,
                cdr_value_array + m,
                cdr_int_array + m,
                cdr_type_array +m,
                &dlgb);
    }

	for( ; i<m; i++) {
		db_cdr_keys[i] = &cdr_attrs[i];
		VAL_TYPE(db_cdr_vals+i)=DB1_STR;
		VAL_NULL(db_cdr_vals+i)=0;
		VAL_STR(db_cdr_vals+i) = cdr_value_array[i];
	}

	if (df->use_table(dh, &acc_cdrs_table /*table*/) < 0) {
		LM_ERR("error in use_table\n");
		goto error;
	}

	if(acc_db_insert_mode==1 && df->insert_delayed!=NULL) {
		if (df->insert_delayed(dh, db_cdr_keys, db_cdr_vals, m) < 0) {
			LM_ERR("failed to insert delayed into database\n");
			goto error;
		}
	} else if(acc_db_insert_mode==2 && df->insert_async!=NULL) {
		if (df->insert_async(dh, db_cdr_keys, db_cdr_vals, m) < 0) {
			LM_ERR("failed to insert async into database\n");
			goto error;
		}
	} else {
		if (df->insert(dh, db_cdr_keys, db_cdr_vals, m) < 0) {
			LM_ERR("failed to insert into database\n");
			goto error;
		}
	}

	/* Free memory allocated by acc_extra.c/extra2strar */
	free_strar_mem( &(cdr_type_array[m-n]), &(cdr_value_array[m-n]), n, m);
	return 0;

error:
    /* Free memory allocated by acc_extra.c/extra2strar */
	free_strar_mem( &(cdr_type_array[m-n]), &(cdr_value_array[m-n]), n, m);
    return -1;
}
Beispiel #10
0
int acc_diam_request( struct sip_msg *req )
{
	int attr_cnt;
	int cnt;
	AAAMessage *send = NULL;
	AAA_AVP *avp;
	struct sip_uri puri;
	str *uri;
	int ret;
	int i;
	int status;
	char tmp[2];
	unsigned int mid;

	attr_cnt = core2strar( req, val_arr, int_arr, type_arr );
	/* last value is not used */
	attr_cnt--;

	if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL) {
		LM_ERR("failed to create new AAA request\n");
		return -1;
	}

	/* AVP_ACCOUNTIG_RECORD_TYPE */
	if( (status = diam_status(req, acc_env.code))<0) {
		LM_ERR("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) {
		LM_ERR("failed to create AVP:no more free memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
		LM_ERR("avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}
	/* SIP_MSGID AVP */
	mid = req->id;
	if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid), 
	sizeof(mid), AVP_DUPLICATE_DATA)) == 0) {
		LM_ERR("failed to create AVP:no more free memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
		LM_ERR("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) {
		LM_ERR("failed to create AVP:no more free memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
		LM_ERR("avp not added \n");
		AAAFreeAVP(&avp);
		goto error;
	}

	/* also the extra attributes */
	attr_cnt += extra2strar( dia_extra, req, val_arr, int_arr, type_arr);

	/* add attributes */
	for(i=0; i<attr_cnt; i++) {
		if((avp=AAACreateAVP(diam_attrs[i], 0,0, val_arr[i].s, val_arr[i].len,
		AVP_DUPLICATE_DATA)) == 0) {
			LM_ERR("failed to create AVP: no more free memory!\n");
			goto error;
		}
		if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
			LM_ERR("avp not added \n");
			AAAFreeAVP(&avp);
			goto error;
		}
	}

	/* and the leg attributes */
	if ( leg_info ) {
	        cnt = legs2strar(leg_info,req,val_arr,int_arr,type_arr,1);
		do {
			for (i=0; i<cnt; i++) {
				if((avp=AAACreateAVP(diam_attrs[attr_cnt+i], 0, 0,
				val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) {
					LM_ERR("failed to create AVP: no more free memory!\n");
					goto error;
				}
				if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) {
					LM_ERR("avp not added \n");
					AAAFreeAVP(&avp);
					goto error;
				}
			}
		} while ( (cnt=legs2strar(leg_info,req,val_arr,int_arr,
					  type_arr,0))!=0 );
	}

	if (get_uri(req, &uri) < 0) {
		LM_ERR("failed to get uri, From/To URI not found\n");
		goto error;
	}

	if (parse_uri(uri->s, uri->len, &puri) < 0) {
		LM_ERR("failed to parse 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) {
		LM_ERR("failed to create AVP:no more free memory!\n");
		goto error;
	}

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

	/* prepare the message to be sent over the network */
	if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS) {
		LM_ERR("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) {
			LM_ERR("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, req->id);
	if(ret == AAA_CONN_CLOSED) {
		LM_NOTICE("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 */
		LM_ERR("message sending to the DIAMETER backend authorization "
				"server failed\n");
		goto error;
	}

	AAAFreeMessage(&send);
	return 1;

error:
	AAAFreeMessage(&send);
	return -1;
}
Beispiel #11
0
/*
 * Check from Radius if URI, whose user and host parts are given as
 * arguments, exists.  If so, loads AVPs based on reply items returned
 * from Radius.  If use_sip_uri_host module parameter has non-zero value,
 * user is send in SA_USER_NAME attribute and host in SA_SIP_URI_HOST
 * attribute.  If is has zero value, user@host is send in SA_USER_NAME
 * attribute.
 */
int radius_does_uri_user_host_exist(struct sip_msg* _m, str user, str host)
{
    char* at, *user_host;
    VALUE_PAIR *send, *received;
    uint32_t service;
    static char msg[4096];
    int extra_cnt, offset, i, res;

    send = received = 0;
    user_host = 0;

    if (!use_sip_uri_host) {

	/* Send user@host in SA_USER_NAME attr */
	user_host = (char*)pkg_malloc(user.len + host.len + 2);
	if (!user_host) {
	    LM_ERR("no more pkg memory\n");
	    return -1;
	}
	at = user_host;
	memcpy(at, user.s, user.len);
	at += user.len;
	*at = '@';
	at++;
	memcpy(at , host.s, host.len);
	at += host.len;
	*at = '\0';
	if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v, user_host,
			   -1, 0)) {
	    LM_ERR("in adding SA_USER_NAME\n");
	    pkg_free(user_host);
	    return -1;
	}

    } else {

	/* Send user in SA_USER_NAME attribute and host in SA_SIP_URI_HOST
          attribute */
	if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v,
			   user.s, user.len, 0)) {
	    LM_ERR("adding User-Name failed\n");
	    return -1;
	}
	if (!rc_avpair_add(rh, &send, uri_attrs[SA_SIP_URI_HOST].v,
			   host.s, host.len, 0)) {
	    LM_ERR("adding SIP-URI-Host failed\n");
	    goto error;
	}
    }

    service = uri_vals[UV_CALL_CHECK].v;
    if (!rc_avpair_add(rh, &send, uri_attrs[SA_SERVICE_TYPE].v,
		       &service, -1, 0)) {
	LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service);
	goto error;
    }

    /* Add extra attributes */
    extra_cnt = extra2strar(uri_extra, _m, val_arr);
    if (extra_cnt == -1) {
	LM_ERR("in getting values of group extra attributes\n");
	goto error;
    }
    offset = SA_STATIC_MAX;
    for (i = 0; i < extra_cnt; i++) {
	if (val_arr[i].len == -1) {
	    /* Add integer attribute */
	    ADD_EXTRA_AVPAIR(uri_attrs, offset+i,
			     &(val_arr[i].s), val_arr[i].len );
	} else {
	    /* Add string attribute */
	    ADD_EXTRA_AVPAIR(uri_attrs, offset+i,
			     val_arr[i].s, val_arr[i].len );
	}
    }

    if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) {
	LM_DBG("success\n");
	if (user_host) pkg_free(user_host);
	rc_avpair_free(send);
	generate_avps(uri_attrs, received);
	rc_avpair_free(received);
	return 1;
    } else {
	if (user_host) pkg_free(user_host);
	rc_avpair_free(send);
	rc_avpair_free(received);
#ifdef REJECT_RC
	if (res == REJECT_RC) {
	    LM_DBG("rejected\n");
	    return -1;
	} else {
	    LM_ERR("failure\n");
	    return -2;
	}
#else
	LM_DBG("failure\n");
	return -1;
#endif
    }

 error:
    rc_avpair_free(send);
    if (user_host) pkg_free(user_host);
    return -1;
}
Beispiel #12
0
int acc_log_request( struct sip_msg *rq)
{
	static char log_msg[MAX_SYSLOG_SIZE];
	static char *log_msg_end=log_msg+MAX_SYSLOG_SIZE-2;
	char *p;
	int n;
	int m;
	int i;
	struct tm *t;

	/* get default values */
	m = core2strar( rq, val_arr, int_arr, type_arr);

	/* get extra values */
	m += extra2strar( log_extra, rq, val_arr+m, int_arr+m, type_arr+m);

	for ( i=0,p=log_msg ; i<m ; i++ ) {
		if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) {
			LM_WARN("acc message too long, truncating..\n");
			p = log_msg_end;
			break;
		}
		*(p++) = A_SEPARATOR_CHR;
		memcpy(p, log_attrs[i].s, log_attrs[i].len);
		p += log_attrs[i].len;
		*(p++) = A_EQ_CHR;
		if (val_arr[i].s != NULL) {
			memcpy(p, val_arr[i].s, val_arr[i].len);
			p += val_arr[i].len;
		}
	}

	/* get per leg attributes */
	if ( leg_info ) {
		n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m, 1);
		do {
			for (i=m; i<m+n; i++) {
				if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) {
					LM_WARN("acc message too long, truncating..\n");
					p = log_msg_end;
					break;
				}
				*(p++) = A_SEPARATOR_CHR;
				memcpy(p, log_attrs[i].s, log_attrs[i].len);
				p += log_attrs[i].len;
				*(p++) = A_EQ_CHR;
				if (val_arr[i].s != NULL) {
					memcpy(p, val_arr[i].s, val_arr[i].len);
					p += val_arr[i].len;
				}
			}
		} while (p!=log_msg_end && (n=legs2strar(leg_info,rq,val_arr+m,
							int_arr+m,type_arr+m,
							0))!=0);
	}

	/* terminating line */
	*(p++) = '\n';
	*(p++) = 0;

	if(acc_time_mode==1) {
		LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu;%s=%u%s",
			acc_env.text.len, acc_env.text.s,(unsigned long)acc_env.ts,
			acc_time_exten.s, (unsigned int)acc_env.tv.tv_usec,
			log_msg);
	} else if(acc_time_mode==2) {
		LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu;%s=%.3f%s",
			acc_env.text.len, acc_env.text.s,(unsigned long)acc_env.ts,
			acc_time_attr.s,
			(((double)(acc_env.tv.tv_sec * 1000)
							+ (acc_env.tv.tv_usec / 1000)) / 1000),
			log_msg);
	} else if(acc_time_mode==3 || acc_time_mode==4) {
		if(acc_time_mode==3) {
			t = localtime(&acc_env.ts);
		} else {
			t = gmtime(&acc_env.ts);
		}
		if(strftime(acc_time_format_buf, ACC_TIME_FORMAT_SIZE,
					acc_time_format, t)<=0) {
			acc_time_format_buf[0] = '\0';
		}
		LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu;%s=%s%s",
			acc_env.text.len, acc_env.text.s,(unsigned long)acc_env.ts,
			acc_time_attr.s,
			acc_time_format_buf,
			log_msg);
	} else {
		LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu%s",
			acc_env.text.len, acc_env.text.s,(unsigned long)acc_env.ts,
			log_msg);
	}

	return 1;
}
Beispiel #13
0
int acc_aaa_request( struct sip_msg *req, struct sip_msg *rpl)
{
	int attr_cnt;
	aaa_message *send;
	int offset, i, av_type;
	aaa_map *r_stat;

	if ((send = proto.create_aaa_message(conn, AAA_ACCT)) == NULL) {
		LM_ERR("failed to create new aaa message for acct\n");
		return -1;
	}

	attr_cnt = core2strar( req, val_arr);
	/* not interested in the last 2 values */
	attr_cnt -= 2;

	r_stat = aaa_status( req, acc_env.code); /* AAA PROTOCOL status */
	ADD_AAA_AVPAIR( RA_ACCT_STATUS_TYPE, &(r_stat->value), -1);

	av_type = rd_vals[RV_SIP_SESSION].value; /* session*/
	ADD_AAA_AVPAIR( RA_SERVICE_TYPE, &av_type, -1);

	av_type = (uint32_t)acc_env.code; /* status=integer */
	ADD_AAA_AVPAIR( RA_SIP_RESPONSE_CODE, &av_type, -1);

	av_type = req->REQ_METHOD; /* method */
	ADD_AAA_AVPAIR( RA_SIP_METHOD, &av_type, -1);

	/* unix time */
	av_type = (uint32_t)acc_env.ts;
	ADD_AAA_AVPAIR( RA_TIME_STAMP, &av_type, -1);

	/* add extra also */
	attr_cnt += extra2strar( aaa_extra, req, rpl, val_arr+attr_cnt, 0);

	/* add the values for the vector - start from 1 instead of
	 * 0 to skip the first value which is the METHOD as string */
	offset = RA_STATIC_MAX-1;
	for (i = 1; i < attr_cnt; i++)
		ADD_AAA_AVPAIR( offset + i, val_arr[i].s, val_arr[i].len );

	/* call-legs attributes also get inserted */
	if (leg_info) {
		offset += attr_cnt;
		attr_cnt = legs2strar(leg_info,req,val_arr,1);
		do {
			for (i = 0; i < attr_cnt; i++)
				ADD_AAA_AVPAIR( offset+i, val_arr[i].s, val_arr[i].len );
		} while ((attr_cnt = legs2strar(leg_info,req,val_arr,0)) != 0);
	}

	if (proto.send_aaa_request(conn, send, NULL)) {
		LM_ERR("Radius accounting request failed for status: '%s' "
			"Call-Id: '%.*s' \n",r_stat->name,
			req->callid->body.len, req->callid->body.s);
		goto error;
	}

	proto.destroy_aaa_message(conn, send);
	return 1;

error:
	proto.destroy_aaa_message(conn, send);
	return -1;
}
Beispiel #14
0
/*
 * Loads from Radius callee's AVPs based on pvar argument.
 * Returns 1 if Radius request succeeded and -1 otherwise.
 */
int radius_load_callee_avps(struct sip_msg* _m, char* _callee, char* _s2)
{
    str user;
    VALUE_PAIR *send, *received;
    uint32_t service;
    static char msg[4096];
    int extra_cnt, offset, i, res;

    send = received = 0;

    if ((_callee == NULL) ||
	(fixup_get_svalue(_m, (gparam_p)_callee, &user) != 0)) {
	LM_ERR("invalid callee parameter");
	return -1;
    }

    if (!rc_avpair_add(rh, &send, callee_attrs[SA_USER_NAME].v,
		       user.s, user.len, 0)) {
	LM_ERR("in adding SA_USER_NAME\n");
	return -1;
    }

    service = callee_vals[EV_SIP_CALLEE_AVPS].v;
    if (!rc_avpair_add(rh, &send, callee_attrs[SA_SERVICE_TYPE].v,
		       &service, -1, 0)) {
	LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service);
	goto error;
    }

    /* Add extra attributes */
    extra_cnt = extra2strar(callee_extra, _m, val_arr);
    if (extra_cnt == -1) {
	LM_ERR("in getting values of callee extra attributes\n");
	goto error;
    }
    offset = SA_STATIC_MAX;
    for (i = 0; i < extra_cnt; i++) {
	if (val_arr[i].len == -1) {
	    /* Add integer attribute */
	    ADD_EXTRA_AVPAIR(callee_attrs, offset+i,
			     &(val_arr[i].s), val_arr[i].len );
	} else {
	    /* Add string attribute */
	    ADD_EXTRA_AVPAIR(callee_attrs, offset+i,
			     val_arr[i].s, val_arr[i].len );
	}
    }

    if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) {
	LM_DBG("success\n");
	rc_avpair_free(send);
	generate_avps(callee_attrs, received);
	rc_avpair_free(received);
	return 1;
    } else {
	rc_avpair_free(send);
	rc_avpair_free(received);
#ifdef REJECT_RC
	if (res == REJECT_RC) {
	    LM_DBG("rejected\n");
	    return -1;
	} else {
	    LM_ERR("failure\n");
	    return -2;
	}
#else
	LM_DBG("failure\n");
	return -1;
#endif
    }

 error:
    rc_avpair_free(send);
    return -1;
}
Beispiel #15
0
int acc_db_request( struct sip_msg *rq)
{
	int m;
	int n;
	int i;
	struct tm *t;

	/* formated database columns */
	m = core2strar( rq, val_arr, int_arr, type_arr );

	for(i=0; i<m; i++)
		VAL_STR(db_vals+i) = val_arr[i];
	/* time value */
	VAL_TIME(db_vals+(m++)) = acc_env.ts;
	/* extra time value */
	if(acc_time_mode==1) {
		VAL_INT(db_vals+(m++)) = (int)acc_env.tv.tv_sec;
		i++;
		VAL_INT(db_vals+(m++)) = (int)acc_env.tv.tv_usec;
		i++;
	} else if(acc_time_mode==2) {
		VAL_DOUBLE(db_vals+(m++)) = ((double)(acc_env.tv.tv_sec * 1000)
							+ (acc_env.tv.tv_usec / 1000)) / 1000;
		i++;
	} else if(acc_time_mode==3 || acc_time_mode==4) {
		if(acc_time_mode==3) {
			t = localtime(&acc_env.ts);
		} else {
			t = gmtime(&acc_env.ts);
		}
		if(strftime(acc_time_format_buf, ACC_TIME_FORMAT_SIZE,
					acc_time_format, t)<=0) {
			acc_time_format_buf[0] = '\0';
		}
		VAL_STRING(db_vals+(m++)) = acc_time_format_buf;
		i++;
	}

	/* extra columns */
	m += extra2strar( db_extra, rq, val_arr+m, int_arr+m, type_arr+m);

	for( i++ ; i<m; i++)
		VAL_STR(db_vals+i) = val_arr[i];

	if (acc_dbf.use_table(db_handle, &acc_env.text/*table*/) < 0) {
		LM_ERR("error in use_table\n");
		return -1;
	}

	/* multi-leg columns */
	if ( !leg_info ) {
		if(acc_db_insert_mode==1 && acc_dbf.insert_delayed!=NULL) {
			if (acc_dbf.insert_delayed(db_handle, db_keys, db_vals, m) < 0) {
				LM_ERR("failed to insert delayed into database\n");
				return -1;
			}
		} else if(acc_db_insert_mode==2 && acc_dbf.insert_async!=NULL) {
			if (acc_dbf.insert_async(db_handle, db_keys, db_vals, m) < 0) {
				LM_ERR("failed to insert async into database\n");
				return -1;
			}
		} else {
			if (acc_dbf.insert(db_handle, db_keys, db_vals, m) < 0) {
				LM_ERR("failed to insert into database\n");
				return -1;
			}
		}
	} else {
  	        n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m,1);
		do {
			for (i=m; i<m+n; i++)
				VAL_STR(db_vals+i)=val_arr[i];
			if(acc_db_insert_mode==1 && acc_dbf.insert_delayed!=NULL) {
				if(acc_dbf.insert_delayed(db_handle,db_keys,db_vals,m+n)<0) {
					LM_ERR("failed to insert delayed into database\n");
					return -1;
				}
			} else if(acc_db_insert_mode==2 && acc_dbf.insert_async!=NULL) {
				if(acc_dbf.insert_async(db_handle,db_keys,db_vals,m+n)<0) {
					LM_ERR("failed to insert async into database\n");
					return -1;
				}
			} else {
				if (acc_dbf.insert(db_handle, db_keys, db_vals, m+n) < 0) {
					LM_ERR("failed to insert into database\n");
					return -1;
				}
			}
		}while ( (n=legs2strar(leg_info,rq,val_arr+m,int_arr+m,
				       type_arr+m,0))!=0 );
	}

	return 1;
}
Beispiel #16
0
/*
 * Check from Radius if a user belongs to a group. User-Name is given in
 * first string argment that may contain pseudo variables.  SIP-Group is
 * given in second string variable that may not contain pseudo variables.
 * Service-Type is Group-Check.
 */
int radius_is_user_in(struct sip_msg* _m, char* _user, char* _group)
{
    str user, *group;
    VALUE_PAIR *send, *received;
    uint32_t service;
    static char msg[4096];
    int extra_cnt, offset, i, res;

    send = received = 0;

    if ((_user == NULL) ||
	(fixup_get_svalue(_m, (gparam_p)_user, &user) != 0)) {
	LM_ERR("invalid user parameter");
	return -1;
    }

    if (!rc_avpair_add(rh, &send, group_attrs[SA_USER_NAME].v,
		       user.s, user.len, 0)) {
	LM_ERR("in adding SA_USER_NAME\n");
	return -1;
    }

    group = (str*)_group;
    if ((group == NULL) || (group->len == 0)) {
	LM_ERR("invalid group parameter");
	goto error;
    }
    if (!rc_avpair_add(rh, &send, group_attrs[SA_SIP_GROUP].v,
		       group->s, group->len, 0)) {
	LM_ERR("in adding SA_SIP_GROUP\n");
	goto error;
    }

    service = group_vals[GV_GROUP_CHECK].v;
    if (!rc_avpair_add(rh, &send, group_attrs[SA_SERVICE_TYPE].v,
		       &service, -1, 0)) {
	LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service);
	goto error;
    }

    /* Add extra attributes */
    extra_cnt = extra2strar(group_extra, _m, val_arr);
    if (extra_cnt == -1) {
	LM_ERR("in getting values of group extra attributes\n");
	goto error;
    }
    offset = SA_STATIC_MAX;
    for (i = 0; i < extra_cnt; i++) {
	if (val_arr[i].len == -1) {
	    /* Add integer attribute */
	    ADD_EXTRA_AVPAIR(group_attrs, offset+i,
			     &(val_arr[i].s), val_arr[i].len );
	} else {
	    /* Add string attribute */
	    ADD_EXTRA_AVPAIR(group_attrs, offset+i,
			     val_arr[i].s, val_arr[i].len );
	}
    }

    if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) {
	LM_DBG("success\n");
	rc_avpair_free(send);
	generate_avps(group_attrs, received);
	rc_avpair_free(received);
	return 1;
    } else {
	rc_avpair_free(send);
	rc_avpair_free(received);
#ifdef REJECT_RC
	if (res == REJECT_RC) {
	    LM_DBG("rejected\n");
	    return -1;
	} else {
	    LM_ERR("failure\n");
	    return -2;
	}
#else
	LM_DBG("failure\n");
	return -1;
#endif
    }

 error:
    rc_avpair_free(send);
    return -1;
}
Beispiel #17
0
int acc_rad_request( struct sip_msg *req )
{
	int attr_cnt;
	VALUE_PAIR *send;
	UINT4 av_type;
	int offset;
	int i;

	send=NULL;

	attr_cnt = core2strar( req, val_arr, int_arr, type_arr );
	/* not interested in the last 2 values */
	attr_cnt -= 2;

	av_type = rad_status( req, acc_env.code); /* RADIUS status */
	ADD_RAD_AVPAIR( RA_ACCT_STATUS_TYPE, &av_type, -1);

	av_type = rd_vals[RV_SIP_SESSION].v; /* session*/
	ADD_RAD_AVPAIR( RA_SERVICE_TYPE, &av_type, -1);

	av_type = (UINT4)acc_env.code; /* status=integer */
	ADD_RAD_AVPAIR( RA_SIP_RESPONSE_CODE, &av_type, -1);

	av_type = req->REQ_METHOD; /* method */
	ADD_RAD_AVPAIR( RA_SIP_METHOD, &av_type, -1);

	/* unix time */
	av_type = (UINT4)acc_env.ts;
	ADD_RAD_AVPAIR( RA_TIME_STAMP, &av_type, -1);

	/* add extra also */
	attr_cnt += extra2strar(rad_extra, req, val_arr+attr_cnt,
				int_arr+attr_cnt, type_arr+attr_cnt);

	/* add the values for the vector - start from 1 instead of
	 * 0 to skip the first value which is the METHOD as string */
	offset = RA_STATIC_MAX-1;
	for( i=1; i<attr_cnt; i++) {
	    switch (type_arr[i]) {
	    case TYPE_STR:
		ADD_RAD_AVPAIR(offset+i, val_arr[i].s, val_arr[i].len);
		break;
	    case TYPE_INT:
		ADD_RAD_AVPAIR(offset+i, &(int_arr[i]), -1);
		break;
	    default:
		break;
	    }
	}

	/* call-legs attributes also get inserted */
	if ( leg_info ) {
		offset += attr_cnt;
		attr_cnt = legs2strar(leg_info,req,val_arr,int_arr,type_arr,1);
		do {
			for (i=0; i<attr_cnt; i++)
				ADD_RAD_AVPAIR( offset+i, val_arr[i].s, val_arr[i].len );
		}while ( (attr_cnt=legs2strar(leg_info,req,val_arr,int_arr,
					      type_arr, 0))!=0 );
	}

	if (rc_acct(rh, SIP_PORT, send)!=OK_RC) {
		LM_ERR("radius-ing failed\n");
		goto error;
	}
	rc_avpair_free(send);
	return 1;

error:
	rc_avpair_free(send);
	return -1;
}
Beispiel #18
0
/*
 * Check from Radius if URI user given as argument belongs to a local user.
 * If so, loads AVPs based on reply items returned from Radius.
 */
int radius_does_uri_user_exist(struct sip_msg* _m, str user)
{
    static char msg[4096];
    VALUE_PAIR *send, *received;
    uint32_t service;
    int res, extra_cnt, offset, i;
    
    send = received = 0;
    
    if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v,
		       user.s, user.len, 0)) {
	LM_ERR("in adding SA_USER_NAME\n");
	return -1;
    }
    
    service = uri_vals[UV_CALL_CHECK].v;
    if (!rc_avpair_add(rh, &send, uri_attrs[SA_SERVICE_TYPE].v,
		       &service, -1, 0)) {
	LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service);
	goto error;
    }

    /* Add extra attributes */
    extra_cnt = extra2strar(uri_extra, _m, val_arr);
    if (extra_cnt == -1) {
	LM_ERR("in getting values of group extra attributes\n");
	goto error;
    }
    offset = SA_STATIC_MAX;
    for (i = 0; i < extra_cnt; i++) {
	if (val_arr[i].len == -1) {
	    /* Add integer attribute */
	    ADD_EXTRA_AVPAIR(uri_attrs, offset+i,
			     &(val_arr[i].s), val_arr[i].len );
	} else {
	    /* Add string attribute */
	    ADD_EXTRA_AVPAIR(uri_attrs, offset+i,
			     val_arr[i].s, val_arr[i].len );
	}
    }

    if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) {
	LM_DBG("success\n");
	rc_avpair_free(send);
	generate_avps(uri_attrs, received);
	rc_avpair_free(received);
	return 1;
    } else {
	rc_avpair_free(send);
	rc_avpair_free(received);
#ifdef REJECT_RC
	if (res == REJECT_RC) {
	    LM_DBG("rejected\n");
	    return -1;
	} else {
	    LM_ERR("failure\n");
	    return -2;
	}
#else
	LM_DBG("failure\n");
	return -1;
#endif
    }

 error:
    rc_avpair_free(send);
    return -1;
}
Beispiel #19
0
/*
 * This function creates and submits radius authentication request as per
 * draft-sterman-aaa-sip-00.txt.  In addition, _user parameter is included
 * in the request as value of a SER specific attribute type SIP-URI-User,
 * which can be be used as a check item in the request.  Service type of
 * the request is Authenticate-Only.
 */
int radius_authorize_sterman(struct sip_msg* _msg, dig_cred_t* _cred, str* _method, str* _user) 
{
	static char msg[4096];
	VALUE_PAIR *send, *received;
	uint32_t service;
	str method, user, user_name;
	str *ruri;
	int extra_cnt, offset, i;
		
	send = received = 0;

	if (!(_cred && _method && _user)) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	method = *_method;
	user = *_user;
	
	/*
	 * Add all the user digest parameters according to the qop defined.
	 * Most devices tested only offer support for the simplest digest.
	 */
	if (_cred->username.domain.len || !append_realm_to_username) {
		if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, _cred->username.whole.s, _cred->username.whole.len, 0)) {
			LM_ERR("unable to add User-Name attribute\n");
			goto err;
		}
	} else {
		user_name.len = _cred->username.user.len + _cred->realm.len + 1;
		user_name.s = pkg_malloc(user_name.len);
		if (!user_name.s) {
			LM_ERR("no pkg memory left\n");
			return -3;
		}
		memcpy(user_name.s, _cred->username.whole.s, _cred->username.whole.len);
		user_name.s[_cred->username.whole.len] = '@';
		memcpy(user_name.s + _cred->username.whole.len + 1, _cred->realm.s,
			_cred->realm.len);
		if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, user_name.s,
		user_name.len, 0)) {
			LM_ERR("unable to add User-Name attribute\n");
			pkg_free(user_name.s);
			goto err;
		}
		pkg_free(user_name.s);
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_USER_NAME].v, 
	_cred->username.whole.s, _cred->username.whole.len, 0)) {
		LM_ERR("unable to add Digest-User-Name attribute\n");
		goto err;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_REALM].v, _cred->realm.s,
	_cred->realm.len, 0)) {
		LM_ERR("unable to add Digest-Realm attribute\n");
		goto err;
	}
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE].v, _cred->nonce.s,
	_cred->nonce.len, 0)) {
		LM_ERR("unable to add Digest-Nonce attribute\n");
		goto err;
	}

	if (use_ruri_flag < 0 || isflagset(_msg, use_ruri_flag) != 1) {
		ruri = &_cred->uri;
	} else {
		ruri = GET_RURI(_msg);
	}
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_URI].v, ruri->s,
	ruri->len, 0)) {
		LM_ERR("unable to add Digest-URI attribute\n");
		goto err;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_METHOD].v, method.s,
	method.len, 0)) {
		LM_ERR("unable to add Digest-Method attribute\n");
		goto err;
	}
	
	/* 
	 * Add the additional authentication fields according to the QOP.
	 */
	if (_cred->qop.qop_parsed == QOP_AUTH) {
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v, "auth", 4, 0)) {
			LM_ERR("unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v, 
		_cred->nc.s, _cred->nc.len, 0)) {
			LM_ERR("unable to add Digest-CNonce-Count attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v, 
		_cred->cnonce.s, _cred->cnonce.len, 0)) {
			LM_ERR("unable to add Digest-CNonce attribute\n");
			goto err;
		}
	} else if (_cred->qop.qop_parsed == QOP_AUTHINT) {
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v,
		"auth-int", 8, 0)) {
			LM_ERR("unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v,
		_cred->nc.s, _cred->nc.len, 0)) {
			LM_ERR("unable to add Digest-Nonce-Count attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v,
		_cred->cnonce.s, _cred->cnonce.len, 0)) {
			LM_ERR("unable to add Digest-CNonce attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_BODY_DIGEST].v, 
		_cred->opaque.s, _cred->opaque.len, 0)) {
			LM_ERR("unable to add Digest-Body-Digest attribute\n");
			goto err;
		}
		
	} else  {
		/* send nothing for qop == "" */
	}

	/* Add the response... What to calculate against... */
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_RESPONSE].v, 
	_cred->response.s, _cred->response.len, 0)) {
		LM_ERR("unable to add Digest-Response attribute\n");
		goto err;
	}

	/* Indicate the service type, Authenticate only in our case */
	service = vals[V_SIP_SESSION].v;
	if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) {
		LM_ERR("unable to add Service-Type attribute\n");
		goto err;
	}

	/* Add SIP URI as a check item */
	if (!rc_avpair_add(rh,&send,attrs[A_SIP_URI_USER].v,user.s,user.len,0)) {
		LM_ERR("unable to add Sip-URI-User attribute\n");
		goto err;
	}

	if (attrs[A_CISCO_AVPAIR].n != NULL) {
		if (add_cisco_vsa(&send, _msg)) {
			goto err;
		}
	}

	/* Add extra attributes */
	extra_cnt = extra2strar(auth_extra, _msg, val_arr);
	if (extra_cnt == -1) {
	    LM_ERR("in getting values of extra attributes\n");
	    goto err;
	}
	offset = A_MAX;
	for (i = 0; i < extra_cnt; i++) {
	    if (val_arr[i].len == -1) {
		/* Add integer attribute */
		ADD_EXTRA_AVPAIR(attrs, offset+i,
				 &(val_arr[i].s), val_arr[i].len );
	    } else {
		/* Add string attribute */
		ADD_EXTRA_AVPAIR(attrs, offset+i,
				 val_arr[i].s, val_arr[i].len );
	    }
	}

	/* Send request */
	if ((i = rc_auth(rh, SIP_PORT, send, &received, msg)) == OK_RC) {
		LM_DBG("Success\n");
		rc_avpair_free(send);
		send = 0;

		generate_avps(received);

		rc_avpair_free(received);
		return 1;
	} else {
#ifdef REJECT_RC
                if (i == REJECT_RC) {
                        LM_DBG("Failure\n");
                        goto err;
                }
#endif 
		LM_ERR("authorization failed. RC auth returned %d\n", i);
	}

 err:
	if (send) rc_avpair_free(send);
	if (received) rc_avpair_free(received);
	return -1;
}