/** * update Granted Service Unit timers based on CCA, for onw we assume on one MSCC per session and only TIME based supported */ inline void update_gsu_response_timers(cdp_cc_acc_session_t* session, AAAMessage* msg) { AAA_AVP *avp; AAA_AVP_LIST mscc_avp_list; AAA_AVP_LIST y; AAA_AVP *z; avp = AAAFindMatchingAVP(msg, 0, AVP_Multiple_Services_Credit_Control, 0, 0); if (!avp) { LM_WARN("Trying to update GSU timers but there is no MSCC AVP in the CCA response\n"); return; } mscc_avp_list = AAAUngroupAVPS(avp->data); AAA_AVP *mscc_avp = mscc_avp_list.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) { case AVP_Granted_Service_Unit: y = AAAUngroupAVPS(mscc_avp->data); z = y.head; while (z) { switch (z->code) { case AVP_CC_Time: session->reserved_units = get_4bytes(z->data.s); break; default: LM_DBG("ignoring AVP in GSU group with code:[%d]\n", z->code); } z = z->next; } break; case AVP_Validity_Time: session->reserved_units_validity_time = get_4bytes(mscc_avp->data.s); break; case AVP_Final_Unit_Indication: y = AAAUngroupAVPS(mscc_avp->data); z = y.head; while (z) { switch (z->code) { case AVP_Final_Unit_Action: session->fua = get_4bytes(z->data.s); break; default: LM_DBG("ignoring AVP in FUI group with code:[%d]\n", z->code); } z = z->next; } break; } mscc_avp = mscc_avp->next; } AAAFreeAVPList(&mscc_avp_list); AAAFreeAVPList(&y); }
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; } } }
/** * 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; }
/** * 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; }