inline int cdp_avp_get_Enumerated(AAA_AVP *avp,int32_t *data)
{
	int32_t x=0;
	if (!avp || avp->data.len<4) {
		LOG(L_ERR,"Error decoding Enumerated from data len < 4 bytes!\n");
		return 0;
	}
	x = get_4bytes(avp->data.s);
	if (data) *data = x;
	return 1;
}
Beispiel #2
0
/**
 * Returns the SIP-Number-Auth-Items AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns the number or 0 on error
 */
inline int cxdx_get_sip_number_auth_items(AAAMessage *msg, int *data)
{
	str s;
	s = cxdx_get_avp(msg,
		AVP_IMS_SIP_Number_Auth_Items,
		IMS_vendor_id_3GPP,
		__FUNCTION__);
	if (!s.s) return 0;
	*data = get_4bytes(s.s);
	return 1;
}
Beispiel #3
0
/**
 * Returns the Result-Code AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns the AVP payload on success or an empty string on error
 */
inline int cxdx_get_result_code(AAAMessage *msg, int *data)
{
	str s;
	s = cxdx_get_avp(msg,
		AVP_Result_Code,
		0,
		__FUNCTION__);
	if (!s.s) return 0;
	*data = get_4bytes(s.s);
	return 1;
}
Beispiel #4
0
/**
 * Returns the Accounting-Record-Type AVP of a Diameter message.
 * @param msg - the Diameter message
 * @returns AVP payload on success or an empty string on error
 */
inline int Rf_get_accounting_record_type(AAAMessage *msg, int *data)
{
	str s;
	s = Rf_get_avp(msg,
		AVP_Accounting_Record_Type,
		0,
		__FUNCTION__);
	if (!s.s) return 0;
	*data = get_4bytes(s.s);
	return 1;
}
Beispiel #5
0
/**
 * Returns the Server-Assignment-Type AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns the AVP payload on success or an empty string on error
 */
inline int Cx_get_server_assignment_type(AAAMessage *msg, int *data)
{
	str s;
	s = Cx_get_avp(msg,
		AVP_IMS_Server_Assignment_Type,
		IMS_vendor_id_3GPP,
		__FUNCTION__);
	if (!s.s) return 0;
	*data = get_4bytes(s.s);
	return 1;
}
Beispiel #6
0
/**
 * Returns the User-Data-Available AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns the AVP payload on success or an empty string on error
 */
inline int Cx_get_userdata_available(AAAMessage *msg, int *data)
{
	str s;
	s = Cx_get_avp(msg,
		AVP_IMS_User_Data_Already_Available,
		IMS_vendor_id_3GPP,
		__FUNCTION__);
	if (!s.s) return 0;
	*data = get_4bytes(s.s);
	return 1;
}
Beispiel #7
0
/**
 * Returns the Authorization-Type AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns the AVP payload on success or an empty string on error
 */
inline int Cx_get_authorization_type(AAAMessage *msg, int *data)
{
	str s;
	s = Cx_get_avp(msg,
		AVP_IMS_User_Authorization_Type,
		IMS_vendor_id_3GPP,
		__FUNCTION__);
	if (!s.s) return 0;
	*data = get_4bytes(s.s);
	return 1;
}
int get_auth_session_state(AAAMessage* msg)
{
        if (!msg) goto error;
        AAA_AVP* rc = AAAFindMatchingAVP(msg, 0, AVP_Auth_Session_State, 0, 0);
        if (!rc) goto error;
        return get_4bytes(rc->data.s);

error:
        LOG(L_DBG, "ERR:get_auth_session_state(): no AAAMessage or Auth Session State not found\n");
        return STATE_MAINTAINED;
}
Beispiel #9
0
int get_result_code(AAAMessage* msg)
{
	if (!msg) goto error;
	AAA_AVP* rc = AAAFindMatchingAVP(msg, 0, AVP_Result_Code, 0, 0);
	if (!rc) goto error;
	return get_4bytes(rc->data.s);

error:
	LOG(L_INFO, "INF: no AAAMessage or Result Code not found\n");
	return 0;
}
inline int cdp_avp_get_Integer32(AAA_AVP *avp,int32_t *data)
{
	int32_t x=0;
	if (avp->data.len<4) {
		LOG(L_ERR,"Error decoding Integer32 from data len < 4 bytes!\n");
		return 0;
	}
	x = get_4bytes(avp->data.s);
	if (data) *data = x;
	return 1;
}
/**
 * Retrieve the Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs and update the session timers accordingly
 * @param x
 * @param msg
 */
void update_auth_session_timers(cdp_auth_session_t *x,AAAMessage *msg)
{
	AAA_AVP *avp;
	uint32_t session_timeout=0,grace_period=0,auth_lifetime=0;
	
	avp = AAAFindMatchingAVP(msg,0,AVP_Auth_Grace_Period,0,0);
	if (avp &&avp->data.len==4){ 
		grace_period = get_4bytes(avp->data.s);
		x->grace_period = grace_period;
	}
	avp = AAAFindMatchingAVP(msg,0,AVP_Authorization_Lifetime,0,0);
	if (avp &&avp->data.len==4) {
		auth_lifetime = get_4bytes(avp->data.s);
		switch(auth_lifetime){
			case 0:
				x->lifetime = time(0);
				break;
			case 0xFFFFFFFF:
				x->lifetime = -1;
				break;
			default:
				x->lifetime = time(0)+auth_lifetime;
		}
		if (x->timeout!=-1 && x->timeout<x->lifetime) x->timeout = x->lifetime+x->grace_period;
	}
	avp = AAAFindMatchingAVP(msg,0,AVP_Session_Timeout,0,0);
	if (avp &&avp->data.len==4) {
		session_timeout = get_4bytes(avp->data.s);
		switch(session_timeout){
			case 0:
				x->timeout = time(0)+config->default_auth_session_timeout;
				break;
			case 0xFFFFFFFF:
				x->timeout = -1;
				break;
			default:
				x->timeout = time(0)+session_timeout;
		}
		if (!x->lifetime) x->lifetime = x->timeout;
	}
}
Beispiel #12
0
/**
 * Returns the AVP_Credit_perMbyte AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns 1 on success or 0 on error
 */
inline int Rf_get_Credit_perMbyte(AAAMessage *msg, int *data)
{
	AAA_AVP *avp;
	avp = Rf_get_avp(msg,AVP_Credit_perMbyte,0);
	if (!avp)
	{
	LOG(L_ERR,"ERR:Rf_get_Credit_perMbyte: AVP_Credit_perMbyte not found\n");
	return 0;
	}
	*data = get_4bytes(avp->data.s); 
	return 1;
}
Beispiel #13
0
/**
 * Returns the AVP_Accounting_Record_Number AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns 1 on success or 0 on error
 */
inline int Rf_get_accounting_record_type(AAAMessage *msg, int *data)
{
	AAA_AVP *avp;
	avp = Rf_get_avp(msg,AVP_Accounting_Record_Type,0);
	if (!avp)
	{
	LOG(L_ERR,"ERR:Rf_get_accounting_record_type: AVP_Accounting_Record_Type not found\n");
	return 0;
	}
	*data = get_4bytes(avp->data.s); 
	return 1;
}
Beispiel #14
0
/**
 * Returns the AVP_Credit_onceoff AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns 1 on success or 0 on error
 */
inline int Rf_get_Credit_onceoff(AAAMessage *msg, int *data)
{
	AAA_AVP *avp;
	//str s;
	avp = Rf_get_avp(msg,AVP_Credit_onceoff,0);
	if (!avp)
	{
	LOG(L_ERR,"ERR:Rf_get_Credit_onceoff: AVP_Credit_onceoff not found\n");
	return 0;
	}
	*data = get_4bytes(avp->data.s); 
	return 1;
}
Beispiel #15
0
void save_peer_applications(peer *p,AAAMessage *msg)
{
	int total_cnt=0;
	AAA_AVP *avp,*avp_vendor,*avp2;
	AAA_AVP_LIST group;
	int id,vendor;

	if (p->applications) {
		shm_free(p->applications);
		p->applications = 0;
		p->applications_cnt = 0;
	}
	for(avp=msg->avpList.head;avp;avp = avp->next)
		switch (avp->code){
			case AVP_Auth_Application_Id:
			case AVP_Acct_Application_Id:
			case AVP_Vendor_Specific_Application_Id:				
				total_cnt+=2;/* wasteful, but let's skip decoding */	
				break;				
		}
	p->applications_cnt = 0;
	p->applications = shm_malloc(sizeof(app_config)*total_cnt);
	if (!p->applications){	
		LM_ERR("save_peer_applications(): Error allocating %ld bytes! No applications saved...\n",
			(long int)(sizeof(app_config)*total_cnt));
		return;
	}
	for(avp=msg->avpList.head;avp;avp = avp->next)
	{
		switch (avp->code){
			case AVP_Auth_Application_Id:
				id = get_4bytes(avp->data.s);	
				add_peer_application(p,id,0,DP_AUTHORIZATION);	
				break;
			case AVP_Acct_Application_Id:
				id = get_4bytes(avp->data.s);	
				add_peer_application(p,id,0,DP_ACCOUNTING);	
				break;
			case AVP_Vendor_Specific_Application_Id:
				group = AAAUngroupAVPS(avp->data);
				avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);				
				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,0);				
				if (avp_vendor&&avp2){
					vendor = get_4bytes(avp_vendor->data.s);
					id = get_4bytes(avp2->data.s);
					add_peer_application(p,id,vendor,DP_AUTHORIZATION);						
				}
				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,0);				
				if (avp_vendor&&avp2){
					vendor = get_4bytes(avp_vendor->data.s);
					id = get_4bytes(avp2->data.s);
					add_peer_application(p,id,vendor,DP_ACCOUNTING);					
				}
				AAAFreeAVPList(&group);
				break;
				
		}
	}	
}
int getUnits(AAAMessage *msg, int * used, int * service, int * group) {
	AAA_AVP *avp, *req_units, *value, *used_units, *service_avp, *rating_group;
	int units = 0;
	*used = 0;
	*service = 0;
	avp = cdpb.AAAFindMatchingAVP(msg,0,AVP_Multiple_Services_Credit_Control,0,0);
	if (avp) {
		AAA_AVP_LIST list, list2;
		list = cdp_avp->cdp->AAAUngroupAVPS(avp->data);
		req_units = cdpb.AAAFindMatchingAVPList(list, list.head, AVP_Requested_Service_Unit, 0, 0);
		if (req_units) {
			list2 = cdp_avp->cdp->AAAUngroupAVPS(req_units->data);
			value = cdpb.AAAFindMatchingAVPList(list2, list2.head, AVP_CC_Time, 0, 0);
			cdpb.AAAFreeAVPList(&list2);
			if (value)
				units = get_4bytes(value->data.s);
			cdpb.AAAFreeAVPList(&list2);
		}
		service_avp = cdpb.AAAFindMatchingAVPList(list, list.head, AVP_Service_Identifier, 0, 0);
		if (service_avp) {
			*service = get_4bytes(service_avp->data.s);
		}
		used_units = cdpb.AAAFindMatchingAVPList(list, list.head, AVP_Used_Service_Unit, 0, 0);
		if (used_units) {
			list2 = cdp_avp->cdp->AAAUngroupAVPS(used_units->data);
			value = cdpb.AAAFindMatchingAVPList(list2, list2.head, AVP_CC_Time, 0, 0);
			if (value)
				*used = get_4bytes(value->data.s);
			cdpb.AAAFreeAVPList(&list2);
		}
		rating_group = cdpb.AAAFindMatchingAVPList(list, list.head, AVP_Rating_Group, 0, 0);
		if (rating_group) {
			*group = get_4bytes(rating_group->data.s);
		}
		cdpb.AAAFreeAVPList(&list);
	}
	if (*service == 0) LM_WARN("Failed to get service-identifier\n");
	return units;
}
Beispiel #17
0
/**
 * Returns the AVP_Call_Record_Id AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns 1 on success or 0 on error
 */
inline int Rf_get_call_record_id(AAAMessage *msg, int *data)
{
	AAA_AVP *avp;
	avp = Rf_get_avp(msg,AVP_Call_Record_Id,0);
	if (!avp)
	{
	LOG(L_ERR,"ERR:Rf_get_call_record_id: AVP_Call_Record_Id not found\n");
	return 0;
	}
	*data = get_4bytes(avp->data.s); 
	return 1;

}
Beispiel #18
0
/**
 * Process a Capabilities Exchange Request.
 * Checks whether there are common applications.
 * \note Must be called with a lock on the peer.
 * @param p - peer identification
 * @param cer - the CER message
 * @returns the Result-Code of the operation, AAA_SUCCESS or AAA_NO_COMMON_APPLICATION
 */
int Process_CER(peer *p,AAAMessage *cer)
{
	int common_app=0;
	AAA_AVP *avp,*avp_vendor,*avp2;
	AAA_AVP_LIST group;
	int i,id,vendor;
	for(avp=cer->avpList.head;avp;avp = avp->next)
	{
		switch (avp->code){
			case AVP_Auth_Application_Id:
				id = get_4bytes(avp->data.s);	
				for(i=0;i<config->applications_cnt;i++)
					if (id == config->applications[i].id &&
						config->applications[i].vendor==0 &&
						config->applications[i].type==DP_AUTHORIZATION) common_app++;	
				break;
			case AVP_Acct_Application_Id:
				id = get_4bytes(avp->data.s);	
				for(i=0;i<config->applications_cnt;i++)
					if (id == config->applications[i].id &&
						config->applications[i].vendor==0 &&
						config->applications[i].type==DP_ACCOUNTING) common_app++;	
				break;
			case AVP_Vendor_Specific_Application_Id:
				group = AAAUngroupAVPS(avp->data);
				avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);				
				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,0);				
				if (avp_vendor&&avp2){
					vendor = get_4bytes(avp_vendor->data.s);
					id = get_4bytes(avp2->data.s);
					for(i=0;i<config->applications_cnt;i++)
						if (id == config->applications[i].id &&
							config->applications[i].vendor==vendor &&
							config->applications[i].type==DP_AUTHORIZATION) common_app++;	
					
				}
				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,0);				
				if (avp_vendor&&avp2){
					vendor = get_4bytes(avp_vendor->data.s);
					id = get_4bytes(avp2->data.s);
					for(i=0;i<config->applications_cnt;i++)
						if (id == config->applications[i].id &&
							config->applications[i].vendor==vendor &&
							config->applications[i].type==DP_ACCOUNTING) common_app++;	
					
				}
				AAAFreeAVPList(&group);
				break;
				
		}
	}
	
	if (common_app!=0){
		save_peer_applications(p,cer);
		return AAA_SUCCESS;
	}else 
		return AAA_NO_COMMON_APPLICATION;	
}
int get_result_code(AAAMessage* msg)
{
	AAA_AVP *avp;
	AAA_AVP_LIST list;
	list.head=0;
	list.tail=0;
	int rc=-1;
	
        if (!msg) goto error;
        
        for (avp=msg->avpList.tail;avp;avp=avp->prev)
		{
		
			if (avp->code==AVP_Result_Code)
			{
				rc = get_4bytes(avp->data.s);	
				goto finish;
			} else if (avp->code==AVP_Experimental_Result)
			{
				list=AAAUngroupAVPS(avp->data);
				for(avp=list.head;avp;avp=avp->next)
				{
					if (avp->code==AVP_IMS_Experimental_Result_Code)
						{
							rc = get_4bytes(avp->data.s);
							AAAFreeAVPList(&list);
							goto finish;
						}
			 	}
				AAAFreeAVPList(&list);			 					
			}
		}
finish:
		return rc;
error:
        LOG(L_ERR, "ERR:get_result_code(): no AAAMessage or Result Code not found\n");
        return -1;
}
Beispiel #20
0
int rl_list_node_deserialize_long(rlite *db, void **obj, void *context, unsigned char *data)
{
	rl_list *list = context;
	rl_list_node *node = NULL;
	long i = 0, pos = 12;
	int retval;
	RL_CALL(rl_list_node_create, RL_OK, db, list, &node);
	node->size = (long)get_4bytes(data);
	node->left = (long)get_4bytes(&data[4]);
	node->right = (long)get_4bytes(&data[8]);
	for (i = 0; i < node->size; i++) {
		RL_MALLOC(node->elements[i], sizeof(long))
		*(long *)node->elements[i] = get_4bytes(&data[pos]);
		pos += 4;
	}
	*obj = node;
	retval = RL_OK;
cleanup:
	if (retval != RL_OK && node) {
		node->size = i;
		rl_list_node_destroy(db, node);
	}
	return retval;
}
Beispiel #21
0
/**
 * Returns the Capabilities from the grouped AVP from a Diameter message.
 * @param msg - the Diameter message
 * @param m - array to be filled with the retrieved mandatory capabilities
 * @param m_cnt - size of the array above to be filled
 * @param o - array to be filled with the retrieved optional capabilities
 * @param o_cnt - size of the array above to be filled
 * @returns 1 on success 0 on fail
 */
inline int Cx_get_capabilities(AAAMessage *msg,int **m,int *m_cnt,int **o,int *o_cnt)
{
	AAA_AVP_LIST list;
	AAA_AVP *avp;
	str grp;
	grp = Cx_get_avp(msg,
		AVP_IMS_Server_Capabilities,
		IMS_vendor_id_3GPP,
		__FUNCTION__);
	if (!grp.s) return 0;

	list = cdpb.AAAUngroupAVPS(grp);
	
	avp = list.head;
	*m_cnt=0;
	*o_cnt=0;
	while(avp){
		if (avp->code == AVP_IMS_Mandatory_Capability) (*m_cnt)++;
		if (avp->code == AVP_IMS_Optional_Capability) (*o_cnt)++;		
		avp = avp->next;
	}
	avp = list.head;
	*m=shm_malloc(sizeof(int)*(*m_cnt));
	*o=shm_malloc(sizeof(int)*(*o_cnt));
	*m_cnt=0;
	*o_cnt=0;
	while(avp){
		if (avp->code == AVP_IMS_Mandatory_Capability) 
			(*m)[(*m_cnt)++]=get_4bytes(avp->data.s);
		if (avp->code == AVP_IMS_Optional_Capability)		
			(*o)[(*o_cnt)++]=get_4bytes(avp->data.s);
		avp = avp->next;
	}
	cdpb.AAAFreeAVPList(&list);
	return 1;
}
str getSubscriptionId1(AAAMessage *msg, int * type) {
	AAA_AVP *avp, *avp_type, *avp_value;
	str r={0,0};
	avp = cdpb.AAAFindMatchingAVP(msg,0,AVP_Subscription_Id,0,0);
	AAA_AVP_LIST list;
	list = cdp_avp->cdp->AAAUngroupAVPS(avp->data);
	avp_type = cdpb.AAAFindMatchingAVPList(list, list.head, AVP_Subscription_Id_Type, 0, 0);
	avp_value = cdpb.AAAFindMatchingAVPList(list, list.head, AVP_Subscription_Id_Data, 0, 0);
	
	if (avp_type) {
		*type = get_4bytes(avp_type->data.s);
	} else {
		LM_DBG("Failed finding type\n");
		*type = 0;
	}
	if (avp_value==0) {
		LM_DBG("Failed finding value\n");
	} else {
		r = avp_value->data;
	}
	cdpb.AAAFreeAVPList(&list);
	return r;
}
Beispiel #23
0
/**
 * Returns the Experimental-Result-Code AVP from a Diameter message.
 * @param msg - the Diameter message
 * @returns the AVP payload on success or an empty string on error
 */
inline int cxdx_get_experimental_result_code(AAAMessage *msg, int *data)
{
	AAA_AVP_LIST list;
	AAA_AVP *avp;
	str grp;
	grp = cxdx_get_avp(msg,
		AVP_IMS_Experimental_Result,
		0,
		__FUNCTION__);
	if (!grp.s) return 0;

	list = cdpb.AAAUngroupAVPS(grp);
	
	avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Experimental_Result_Code,0,0);
	if (!avp||!avp->data.s) {
		cdpb.AAAFreeAVPList(&list);
		return 0;
	}

	*data = get_4bytes(avp->data.s);
	cdpb.AAAFreeAVPList(&list);

	return 1;
}
Beispiel #24
0
/**
 * Get the first connect peer that matches the routing mechanisms.
 * - First the Destination-Host AVP value is tried if connected (the peer does not have to
 * be in the routing table at all).
 * - Then we look for a connected peer in the specific realm for the Destination-Realm AVP
 * - Then we look for the first connected peer in the default routes
 * @param m - the Diameter message to find the destination peer for
 * @returns - the connected peer or null if none connected found
 */
peer* get_routing_peer(cdp_session_t* cdp_session, AAAMessage *m) {
	str destination_realm = {0, 0}, destination_host = {0, 0};
	AAA_AVP *avp, *avp_vendor, *avp2;
	AAA_AVP_LIST group;
	peer *p;
	routing_realm *rr;
	int app_id = 0, vendor_id = 0;

	LM_DBG("getting diameter routing peer for realm: [%.*s]\n", m->dest_realm->data.len, m->dest_realm->data.s);

	app_id = m->applicationId;
	avp = AAAFindMatchingAVP(m, 0, AVP_Vendor_Specific_Application_Id, 0, AAA_FORWARD_SEARCH);
	if (avp) {
		group = AAAUngroupAVPS(avp->data);
		avp_vendor = AAAFindMatchingAVPList(group, group.head, AVP_Vendor_Id, 0, 0);
		avp2 = AAAFindMatchingAVPList(group, group.head, AVP_Auth_Application_Id, 0, 0);
		if (avp_vendor && avp2) {
			vendor_id = get_4bytes(avp_vendor->data.s);
			app_id = get_4bytes(avp2->data.s);
		}
		avp2 = AAAFindMatchingAVPList(group, group.head, AVP_Acct_Application_Id, 0, 0);
		if (avp_vendor && avp2) {
			vendor_id = get_4bytes(avp_vendor->data.s);
			app_id = get_4bytes(avp2->data.s);
		}
		AAAFreeAVPList(&group);
	}

	avp_vendor = AAAFindMatchingAVP(m, 0, AVP_Vendor_Id, 0, AAA_FORWARD_SEARCH);
	avp = AAAFindMatchingAVP(m, 0, AVP_Auth_Application_Id, 0, AAA_FORWARD_SEARCH);
	if (avp && avp_vendor) {
		vendor_id = get_4bytes(avp_vendor->data.s);
		app_id = get_4bytes(avp->data.s);
	}

	avp = AAAFindMatchingAVP(m, 0, AVP_Acct_Application_Id, 0, AAA_FORWARD_SEARCH);
	if (avp && avp_vendor) {
		vendor_id = get_4bytes(avp_vendor->data.s);
		app_id = get_4bytes(avp->data.s);
	}

	avp = AAAFindMatchingAVP(m, 0, AVP_Destination_Host, 0, AAA_FORWARD_SEARCH);
	if (avp) destination_host = avp->data;

	if (destination_host.len) {
		/* There is a destination host present in the message try and route directly there */
		p = get_peer_by_fqdn(&destination_host);
		if (p && (p->state == I_Open || p->state == R_Open) && peer_handles_application(p, app_id, vendor_id)) {
			p->last_selected = time(NULL);
			return p;
		}
		/* the destination host peer is not connected at the moment, try a normal route then */
	}

	avp = AAAFindMatchingAVP(m, 0, AVP_Destination_Realm, 0, AAA_FORWARD_SEARCH);
	if (avp) destination_realm = avp->data;

	if (!config->r_table) {
		LM_ERR("get_routing_peer(): Empty routing table.\n");
		return 0;
	}

	if (destination_realm.len) {
		/* first search for the destination realm */
		for (rr = config->r_table->realms; rr; rr = rr->next)
			if (rr->realm.len == destination_realm.len &&
					strncasecmp(rr->realm.s, destination_realm.s, destination_realm.len) == 0)
				break;
		if (rr) {
			p = get_first_connected_route(cdp_session, rr->routes, app_id, vendor_id);
			if (p) return p;
			else LM_ERR("get_routing_peer(): No connected Route peer found for Realm <%.*s>. Trying DefaultRoutes next...\n",
					destination_realm.len, destination_realm.s);
		}
	}
	/* if not found in the realms or no destination_realm,
	 * get the first connected host in default routes */
	LM_DBG("no routing peer found, trying default route\n");
	p = get_first_connected_route(cdp_session, config->r_table->routes, app_id, vendor_id);
	if (!p) {
		LM_ERR("get_routing_peer(): No connected DefaultRoute peer found for app_id %d and vendor id %d.\n",
				app_id, vendor_id);
	}
	return p;
}
Beispiel #25
0
/**
 * Retrieve the Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs and update the session timers accordingly
 * @param x
 * @param msg
 */
void update_auth_session_timers(cdp_auth_session_t *x, AAAMessage *msg) {
    AAA_AVP *avp;
    uint32_t session_timeout = 0, grace_period = 0, auth_lifetime = 0;
    int update_grace = 0, update_lifetime = 0;

    avp = AAAFindMatchingAVP(msg, 0, AVP_Auth_Grace_Period, 0, 0);
    if (avp && avp->data.len == 4) {
        grace_period = get_4bytes(avp->data.s);
        update_grace = 1;
    } else {
        if (!avp) {
            grace_period = x->last_requested_grace;
        }
    }
    if (update_grace)
        x->grace_period = grace_period;


    avp = AAAFindMatchingAVP(msg, 0, AVP_Authorization_Lifetime, 0, 0);
    if (avp && avp->data.len == 4) {
        auth_lifetime = get_4bytes(avp->data.s);
        update_lifetime = 1;
        
    } else {
        if (!avp) {
            LM_DBG("using timers from our request as there is nothing in the response (lifetime) - last requested lifetime was [%d]\n", x->last_requested_lifetime);
            if (x->last_requested_lifetime > 0) {
                update_lifetime = 1;
                auth_lifetime = x->last_requested_lifetime;
            }
        }
    }
    if (update_lifetime) {
        switch (auth_lifetime) {
            case 0:
                x->lifetime = time(0);
                break;
            case 0xFFFFFFFF:
                x->lifetime = -1;
                break;
            default:
                x->lifetime = time(0) + auth_lifetime;
        }
        if (x->timeout != -1 && x->timeout < x->lifetime) {
            x->timeout = x->lifetime + x->grace_period;
        }
    }
    
    avp = AAAFindMatchingAVP(msg, 0, AVP_Session_Timeout, 0, 0);
    if (avp && avp->data.len == 4) {
        session_timeout = get_4bytes(avp->data.s);
        switch (session_timeout) {
            case 0:
                x->timeout = time(0) + config->default_auth_session_timeout;
                break;
            case 0xFFFFFFFF:
                x->timeout = -1;
                break;
            default:
                x->timeout = time(0) + session_timeout;
        }
        if (!x->lifetime) x->lifetime = x->timeout;
    }
}
Beispiel #26
0
/**
 * Add Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs to outgoing messages in case they are missing
 * @param x
 * @param msg
 */
void add_auth_session_timers(cdp_auth_session_t *x, AAAMessage *msg) {
    AAA_AVP *avp;
    char data[4];
    uint32_t v;
    uint32_t lifetime, timeout, grace;

    avp = AAAFindMatchingAVP(msg, 0, AVP_Authorization_Lifetime, 0, 0);
    if (!avp) {
        if (x->lifetime == -1) v = 0xFFFFFFFF;
        else {
            v = x->lifetime - time(0);
            if (v < 0) v = 0;
        }
        x->last_requested_lifetime = v;
        set_4bytes(data, v);
        avp = AAACreateAVP(AVP_Authorization_Lifetime, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
        if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
    } else {
        if (avp->data.len == 4) {
            lifetime = get_4bytes(avp->data.s);
            switch (lifetime) {
                case 0:
                    x->last_requested_lifetime = 0;
                    break;
                case 0xFFFFFFFF:
                    x->last_requested_lifetime = -1;
                    break;
                default:
                    x->last_requested_lifetime = lifetime;
            }
        }
    }
    if (x->lifetime != -1) {
        avp = AAAFindMatchingAVP(msg, 0, AVP_Auth_Grace_Period, 0, 0);
        if (!avp) {
            v = x->grace_period;
            set_4bytes(data, v);
            avp = AAACreateAVP(AVP_Auth_Grace_Period, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
            if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
            x->last_requested_grace = v;
        } else {
            if (avp->data.len == 4) {
                grace = get_4bytes(avp->data.s);
                switch (grace) {
                    case 0:
                        x->last_requested_grace = 0;
                        break;
                    case 0xFFFFFFFF:
                        x->last_requested_grace = -1;
                        break;
                    default:
                        x->last_requested_grace = grace;
                }
            }
        }
    }
    avp = AAAFindMatchingAVP(msg, 0, AVP_Session_Timeout, 0, 0);
    if (!avp) {
        if (x->timeout == -1) v = 0xFFFFFFFF;
        else {
            v = x->timeout - time(0);
            if (v < 0) v = 0;
        }
        set_4bytes(data, v);
        avp = AAACreateAVP(AVP_Session_Timeout, AAA_AVP_FLAG_MANDATORY, 0, data, 4, AVP_DUPLICATE_DATA);
        if (avp) AAAAddAVPToMessage(msg, avp, msg->avpList.tail);
        x->last_requested_timeout = v;
    } else {
        if (avp->data.len == 4) {
            timeout = get_4bytes(avp->data.s);
            switch (timeout) {
                case 0:
                    x->last_requested_timeout = 0;
                    break;
                case 0xFFFFFFFF:
                    x->last_requested_timeout = -1;
                    break;
                default:
                    x->last_requested_timeout = lifetime;
            }
        }
    }

}
/* This function convert message to message structure */
AAAMessage* AAATranslateMessage( unsigned char* source, unsigned int sourceLen,
				 int attach_buf)
{
  unsigned char *ptr;
  AAAMessage    *msg;
  unsigned char version;
  unsigned int  msg_len;
  AAA_AVP       *avp;
  unsigned int  avp_code;
  unsigned char avp_flags;
  unsigned int  avp_len;
  unsigned int  avp_vendorID;
  unsigned int  avp_data_len;

  /* check the params */
  if( !source || !sourceLen || sourceLen<AAA_MSG_HDR_SIZE) {
    ERROR("ERROR:AAATranslateMessage: invalid buffered received!\n");
    goto error;
  }

  /* inits */
  msg = 0;
  avp = 0;
  ptr = source;

  /* alloc a new message structure */
  msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage));
  if (!msg) {
    ERROR("ERROR:AAATranslateMessage: no more free memory!!\n");
    goto error;
  }
  memset(msg,0,sizeof(AAAMessage));

  /* get the version */
  version = (unsigned char)*ptr;
  ptr += VER_SIZE;
  if (version!=1) {
    ERROR("ERROR:AAATranslateMessage: invalid version [%d]in "
	  "AAA msg\n",version);
    goto error;
  }

  /* message length */
  msg_len = get_3bytes( ptr );
  ptr += MESSAGE_LENGTH_SIZE;
  if (msg_len>sourceLen) {
    ERROR("ERROR:AAATranslateMessage: AAA message len [%d] bigger then"
	  " buffer len [%d]\n",msg_len,sourceLen);
    goto error;
  }

  /* command flags */
  msg->flags = *ptr;
  ptr += FLAGS_SIZE;

  /* command code */
  msg->commandCode = get_3bytes( ptr );
  ptr += COMMAND_CODE_SIZE;

  /* application-Id */
  msg->applicationId = get_4bytes( ptr );
  ptr += APPLICATION_ID_SIZE;

  /* Hop-by-Hop-Id */
  msg->hopbyhopId = *((unsigned int*)ptr);
  ptr += HOP_BY_HOP_IDENTIFIER_SIZE;

  /* End-to-End-Id */
  msg->endtoendId = *((unsigned int*)ptr);
  ptr += END_TO_END_IDENTIFIER_SIZE;

  /* start decoding the AVPS */
  while (ptr < source+msg_len) {
    if (ptr+AVP_HDR_SIZE(0x80)>source+msg_len){
      ERROR("ERROR:AAATranslateMessage: source buffer to short!! "
	    "Cannot read the whole AVP header!\n");
      goto error;
    }
    /* avp code */
    avp_code = get_4bytes( ptr );
    ptr += AVP_CODE_SIZE;
    /* avp flags */
    avp_flags = (unsigned char)*ptr;
    ptr += AVP_FLAGS_SIZE;
    /* avp length */
    avp_len = get_3bytes( ptr );
    ptr += AVP_LENGTH_SIZE;
    if (avp_len<1) {
      ERROR("ERROR:AAATranslateMessage: invalid AVP len [%d]\n",
	    avp_len);
      goto error;
    }
    /* avp vendor-ID */
    avp_vendorID = 0;
    if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
      avp_vendorID = get_4bytes( ptr );
      ptr += AVP_VENDOR_ID_SIZE;
    }
    /* data length */
    avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
    /*check the data length */
    if ( source+msg_len<ptr+avp_data_len) {
      ERROR("ERROR:AAATranslateMessage: source buffer to short!! "
	    "Cannot read a whole data for AVP!\n");
      goto error;
    }

    /* create the AVP */
    avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, (char*)ptr,
			avp_data_len, AVP_DONT_FREE_DATA);
    if (!avp)
      goto error;

    /* link the avp into aaa message to the end */
    AAAAddAVPToMessage( msg, avp, msg->avpList.tail);

    ptr += to_32x_len( avp_data_len );
  }

  /* link the buffer to the message */
  if (attach_buf) {
    msg->buf.s = (char*)source;
    msg->buf.len = msg_len;
  }

  //AAAPrintMessage( msg );
  return  msg;
 error:
  ERROR("ERROR:AAATranslateMessage: message conversion droped!!\n");
  AAAFreeMessage(&msg);
  return 0;
}
Beispiel #28
0
/**
 * Ungroup from a data buffer a list of avps
 * @param buf - payload to ungroup the list from
 * @returns the AAA_AVP_LIST or an empty one on error
 */
AAA_AVP_LIST AAAUngroupAVPS(str buf)
{
	char *ptr;
	AAA_AVP       *avp;
	unsigned int  avp_code;
	unsigned char avp_flags;
	unsigned int  avp_len;
	unsigned int  avp_vendorID;
	unsigned int  avp_data_len;
	AAA_AVP_LIST	lh;

	lh.head=0;
	lh.tail=0;
	ptr = buf.s;

	/* start decoding the AVPS */
	while (ptr < buf.s+buf.len) {
		if (ptr+AVP_HDR_SIZE(0x80)>buf.s+buf.len){
			LM_ERR("hss3g_ungroup_avps: source buffer to short!! "
					"Cannot read the whole AVP header!\n");
			goto error;
		}
		/* avp code */
		avp_code = get_4bytes( ptr );
		ptr += AVP_CODE_SIZE;
		/* avp flags */
		avp_flags = (unsigned char)*ptr;
		ptr += AVP_FLAGS_SIZE;
		/* avp length */
		avp_len = get_3bytes( ptr );
		ptr += AVP_LENGTH_SIZE;
		if (avp_len<1) {
			LM_ERR("hss3g_ungroup_avps: invalid AVP len [%d]\n",
					avp_len);
			goto error;
		}
		/* avp vendor-ID */
		avp_vendorID = 0;
		if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
			avp_vendorID = get_4bytes( ptr );
			ptr += AVP_VENDOR_ID_SIZE;
		}
		/* data length */
		avp_data_len = avp_len - AVP_HDR_SIZE(avp_flags);
		/*check the data length */
		if ( buf.s+buf.len<ptr+avp_data_len) {
			LM_ERR("hss3g_ungroup_avps: source buffer to short!! "
					"Cannot read a whole data for AVP!\n");
			goto error;
		}

		/* create the AVP */
		avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, ptr,
				avp_data_len, AVP_DONT_FREE_DATA);
		if (!avp) {
			LM_ERR("hss3g_ungroup_avps: can't create avp for member of list\n");
			goto error;
		}

		/* link the avp into aaa message to the end */
		avp->next = 0;
		avp->prev = lh.tail;
		if (lh.tail) {
			lh.tail->next=avp;
			lh.tail=avp;
		}
		else {
			lh.tail=avp;
			lh.head=avp;
		}

		ptr += to_32x_len( avp_data_len );
	}
	return lh;

error:
	LM_CRIT("AVP:<%.*s>\n",buf.len,buf.s);
	return lh;
}
Beispiel #29
0
Ro_CCA_t *Ro_parse_CCA_avps(AAAMessage *cca) {
    if (!cca)
        return 0;

    Ro_CCA_t *ro_cca_data = 0;
    mem_new(ro_cca_data, sizeof (Ro_CCR_t), pkg);
    multiple_services_credit_control_t *mscc = 0;
    mem_new(mscc, sizeof (multiple_services_credit_control_t), pkg);
    granted_services_unit_t *gsu = 0;
    mem_new(gsu, sizeof (granted_services_unit_t), pkg);
    final_unit_indication_t *fui = 0;
    mem_new(fui, sizeof (final_unit_indication_t), pkg);
    mscc->granted_service_unit = gsu;
    mscc->final_unit_action = fui;

    mscc->final_unit_action->action = -1;
	mscc->final_unit_action->redirect_server = 0;

    AAA_AVP_LIST* avp_list = &cca->avpList;
    AAA_AVP_LIST mscc_avp_list;
    AAA_AVP_LIST* mscc_avp_list_ptr;

    AAA_AVP *avp = avp_list->head;
    unsigned int x;
    while (avp != NULL) {
        switch (avp->code) {
            case AVP_CC_Request_Type:
                x = get_4bytes(avp->data.s);
                ro_cca_data->cc_request_type = x;
                break;
            case AVP_CC_Request_Number:
                x = get_4bytes(avp->data.s);
                ro_cca_data->cc_request_number = x;
                break;
            case AVP_Multiple_Services_Credit_Control:
                mscc_avp_list = cdp_avp->cdp->AAAUngroupAVPS(avp->data);
                mscc_avp_list_ptr = &mscc_avp_list;
                AAA_AVP *mscc_avp = mscc_avp_list_ptr->head;
                while (mscc_avp != NULL) {
                    LM_DBG("MSCC AVP code is [%i] and data length is [%i]", mscc_avp->code, mscc_avp->data.len);
                    switch (mscc_avp->code) {
                            AAA_AVP_LIST y;
                            AAA_AVP *z;
                        case AVP_Granted_Service_Unit:
                            y = cdp_avp->cdp->AAAUngroupAVPS(mscc_avp->data);
                            z = y.head;
                            while (z) {
                                switch (z->code) {
                                    case AVP_CC_Time:
                                        mscc->granted_service_unit->cc_time = get_4bytes(z->data.s);
                                        break;
                                    default:
                                        LM_ERR("Unsupported Granted Service Unit with code:[%d]\n", z->code);
                                }
                                z = z->next;
                            }
                            cdp_avp->cdp->AAAFreeAVPList(&y);
                            break;
                        case AVP_Validity_Time:
                            mscc->validity_time = get_4bytes(mscc_avp->data.s);
                            break;
						case AVP_Result_Code:
							mscc->resultcode = get_4bytes(mscc_avp->data.s);
							break;
                        case AVP_Final_Unit_Indication:
                            y = cdp_avp->cdp->AAAUngroupAVPS(mscc_avp->data);
                            z = y.head;
                            while (z) {
                                switch (z->code) {
                                    case AVP_Final_Unit_Action:
                                        mscc->final_unit_action->action = get_4bytes(z->data.s);
                                        break;
									case AVP_Redirect_Server:
										LM_DBG("Received redirect server\n");
										redirect_server_t* redirect_server_info = 0;
										mem_new(redirect_server_info, sizeof (redirect_server_t), pkg);
										mscc->final_unit_action->redirect_server = redirect_server_info;
										
										AAA_AVP_LIST yy;
										AAA_AVP *zz;
										yy = cdp_avp->cdp->AAAUngroupAVPS(z->data);
										zz = yy.head;
										while (zz) {
											switch (zz->code) {
												case AVP_Redirect_Address_Type:
													LM_DBG("Received redirect address type\n");
													mscc->final_unit_action->redirect_server->address_type = get_4bytes(zz->data.s);
													break;
												case AVP_Redirect_Server_Address:
													LM_DBG("Received redirect server address of [%.*s]\n", zz->data.len, zz->data.s);
													str_dup_ptr(redirect_server_info->server_address, zz->data, pkg);
													break;	
												default:
													LM_ERR("Unsupported Redirect Server AVP with code:[%d]\n", zz->code);
											}
											zz = zz->next;
											cdp_avp->cdp->AAAFreeAVPList(&yy);
										}
										break;		
                                    default:
                                        LM_ERR("Unsupported Final Unit Indication AVP.\n");
                                }
                                z = z->next;
                            }
                            cdp_avp->cdp->AAAFreeAVPList(&y);
                    }
                    mscc_avp = mscc_avp->next;
                }
                cdp_avp->cdp->AAAFreeAVPList(mscc_avp_list_ptr);
                break;
            case AVP_Result_Code:
                x = get_4bytes(avp->data.s);
                ro_cca_data->resultcode = x;
                break;
        }
        avp = avp->next;
    }
    ro_cca_data->mscc = mscc;
    return ro_cca_data;

out_of_memory:
    LM_ERR("out of pkg memory\n");
    Ro_free_CCA(ro_cca_data);
    return 0;
}
Beispiel #30
0
/**
 * Sends a message to the peer.
 * \note Must be called with a lock on the peer.
 * @param p - peer to send to
 * @param msg - message to send
 */
void Snd_Message(peer *p, AAAMessage *msg)
{
	AAASession *session=0;
	int rcode;
	int send_message_before_session_sm=0;
	LM_DBG("Snd_Message called to peer [%.*s] for %s with code %d \n",
		p->fqdn.len,p->fqdn.s,is_req(msg)?"request":"response",msg->commandCode);
	touch_peer(p);
	if (msg->sessionId) session = cdp_get_session(msg->sessionId->data);
	
	if (session){
		LM_DBG("There is a session of type %d\n",session->type);
		switch (session->type){
			case AUTH_CLIENT_STATEFULL:
				if (is_req(msg)) {
					auth_client_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
					session = 0;
				}
				else {
					if (msg->commandCode == IMS_ASA){
						if (!msg->res_code){
							msg->res_code = AAAFindMatchingAVP(msg,0,AVP_Result_Code,0,0);
						}
						if (!msg->res_code) {
							auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
							session = 0;
						}
						else {
							rcode = get_4bytes(msg->res_code->data.s);
							if (rcode>=2000 && rcode<3000) {
								peer_send_msg(p,msg);
								send_message_before_session_sm=1;
								auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_SUCCESS,msg);
								session = 0;
							}
							else {
								auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
								session = 0;
							}
						}
						
					}else {
						auth_client_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
						session = 0;
					}
				}
				break;
			case AUTH_SERVER_STATEFULL:
				LM_DBG("this message is matched here to see what request or reply it is\n");
				if (is_req(msg))
				{
					if (msg->commandCode== IMS_ASR)
					{
						LM_DBG("ASR\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ASR,msg);
						session = 0;
					} else {
						//would be a RAR but ok!
						LM_DBG("other request\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
						session = 0;
					}
				} else {
					if (msg->commandCode == IMS_STR)
					{
						LM_DBG("STA\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_STA,msg);
						session = 0;
					} else {
						LM_DBG("other reply\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
						session = 0;
					}
				}
				break;				 
			default:
				break;
		}
		if (session) AAASessionsUnlock(session->hash);
	}
	if (!send_message_before_session_sm) peer_send_msg(p,msg);
	
}