/** * Response callback for subscribe */ void r_subscribe_response(struct cell *t,int type,struct tmcb_params *ps) { str req_uri; int expires; r_subscription *s=0; LOG(L_DBG,"DBG:"M_NAME":r_subscribe_response: code %d\n",ps->code); if (!ps->rpl || ps->rpl==(void*) -1) { LOG(L_ERR,"INF:"M_NAME":r_subscribe_response: No reply\n"); return; } if (!cscf_get_to_uri(ps->rpl,&req_uri)){ LOG(L_ERR,"INF:"M_NAME":r_subscribe_response: Error extracting the original Req-URI from To header\n"); return; } s = get_r_subscription(req_uri); if (!s){ LOG(L_ERR,"INF:"M_NAME":r_subscribe_response: received a SUBSCRIBE response but no subscription for <%.*s>\n", req_uri.len,req_uri.s); return; } if (ps->code>=200 && ps->code<300){ expires = cscf_get_expires_hdr(ps->rpl); update_r_subscription(s,expires); tmb.dlg_response_uac(s->dialog, ps->rpl, IS_TARGET_REFRESH); }else if (ps->code==404){ update_r_subscription(s,0); //tmb.dlg_response_uac(s->dialog, ps->rpl, IS_TARGET_REFRESH); }else{ LOG(L_INFO,"INF:"M_NAME":r_subscribe_response: SUBSCRIRE response code %d ignored\n",ps->code); } if (s) subs_unlock(s->hash); }
int get_sip_header_info(struct sip_msg * req, struct sip_msg * reply, int interim, int32_t * acc_record_type, str * sip_method, str * event, uint32_t * expires, str * callid, str * from_uri, str * to_uri){ LOG(L_DBG, "retrieving sip info\n"); sip_method->s = req->first_line.u.request.method.s; sip_method->len = req->first_line.u.request.method.len; if(!interim && sip_method->len == 6 && strncmp(sip_method->s, "INVITE",6) == 0) *acc_record_type = AAA_ACCT_START; else if (sip_method->len == 3 && strncmp(sip_method->s, "BYE",3) == 0) *acc_record_type = AAA_ACCT_STOP; else if (sip_method->len == 7 && strncmp(sip_method->s, "MESSAGE", 7) == 0) *acc_record_type = AAA_ACCT_EVENT; else if(interim && sip_method->len == 6 && (strncmp(sip_method->s, "INVITE", 6) == 0 || strncmp(sip_method->s, "UPDATE", 6) ==0)) *acc_record_type = AAA_ACCT_INTERIM; else *acc_record_type = AAA_ACCT_EVENT; *event = cscf_get_event(req); *expires = cscf_get_expires_hdr(req, 0); *callid = cscf_get_call_id(req, NULL); if(!cscf_get_from_uri(req, from_uri)) goto error; if(!cscf_get_to_uri(req, to_uri)) goto error; LOG(L_DBG, "retrieved sip info : sip_method %.*s acc_record_type %i, event %.*s expires %u " "call_id %.*s from_uri %.*s to_uri %.*s\n", sip_method->len, sip_method->s, *acc_record_type, event->len, event->s, *expires, callid->len, callid->s, from_uri->len, from_uri->s, to_uri->len, to_uri->s); return 1; error: return 0; }
/** * Saves a dialog. * @param msg - the initial request * @param str1 - direction - "orig" or "term" * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error */ int S_save_dialog(struct sip_msg* msg, char* str1, char* str2) { str call_id; s_dialog *d; str aor; char buf1[256],buf2[256]; str uri,tag,ruri,x; time_t t_time; str ses_exp = {0,0}; str refresher = {0,0}; str event = {0,0}; struct hdr_field *h; unsigned int hash; enum s_dialog_direction dir = get_dialog_direction(str1); if (!find_dialog_aor(msg,dir,&aor)){ LOG(L_ERR,"ERR:"M_NAME":S_save_dialog(): Error retrieving %s contact\n",str1); return CSCF_RETURN_BREAK; } call_id = cscf_get_call_id(msg,0); if (!call_id.len) return CSCF_RETURN_FALSE; LOG(L_INFO,"DBG:"M_NAME":S_save_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s); if (is_s_dialog(call_id,aor,dir)){ LOG(L_ERR,"ERR:"M_NAME":S_save_dialog: dialog already exists!\n"); return CSCF_RETURN_TRUE; } d = add_s_dialog(call_id,aor,dir); if (!d) return CSCF_RETURN_FALSE; d->method = get_dialog_method(msg->first_line.u.request.method); STR_SHM_DUP(d->method_str,msg->first_line.u.request.method,"shm"); d->first_cseq = cscf_get_cseq(msg,0); d->last_cseq = d->first_cseq; d->state = DLG_STATE_INITIAL; d->uac_supp_timer = supports_extension(msg, &str_ext_timer); ses_exp = cscf_get_session_expires_body(msg, &h); t_time = cscf_get_session_expires(ses_exp, &refresher); if (!t_time) { d->expires = d_act_time() + 60; d->lr_session_expires = 0; } else { d->expires = d_act_time() + t_time; d->lr_session_expires = t_time; if (refresher.len) STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER"); } cscf_get_from_tag(msg,&tag); cscf_get_from_uri(msg,&x); uri.len = snprintf(buf1,256,"<%.*s>",x.len,x.s); uri.s = buf1; cscf_get_to_uri(msg,&x); ruri.len = snprintf(buf2,256,"<%.*s>",x.len,x.s); ruri.s = buf2; tmb.new_dlg_uac(&call_id, &tag, d->first_cseq,&uri, &ruri, &d->dialog_c); tmb.new_dlg_uas(msg,99,&d->dialog_s); event = cscf_get_event(msg); if (event.len){ STR_SHM_DUP(d->event,event,"shm"); } else d->event = event; d_unlock(d->hash); print_s_dialogs(L_INFO); return CSCF_RETURN_TRUE; out_of_memory: if (d){ hash = d->hash; del_s_dialog(d); d_unlock(hash); } return CSCF_RETURN_ERROR; }
/** * Procedure to calculate the virtual queue ID from an incoming call. * This procedure also sets the 'arrival time' of the call. * The formula is id = md5sum { "REQ/RES:Method:from:to" } * * @param struct sip_msg *msg incoming SIP message * @return pointer to the new allocated call information */ queueID_t * vq_get_call_id (struct sip_msg *msg) { queueID_t *newcall_ID; char type[5]; char string[256]; char method[12]; str from = {NULL, 0}; str to = {NULL, 0}; struct msg_start *fl; //struct hdr_field *hf; int isReq; MD5_CTX Md5Ctx; char HA1[HASHLEN]; DBG ("Generating a queue ID...\n"); memset (type, 0, sizeof(type)); memset (string, 0, sizeof(string)); memset (method, 0, sizeof(method)); fl = &msg->first_line; isReq = fl->type; if (isReq != SIP_REQUEST) { DBG ("Not a SIP request"); return NULL; } newcall_ID = shm_malloc (sizeof(queueID_t)); if (!newcall_ID) { ERR ("Could not allocate memory !\n"); return NULL; } // init time in the call_ID gettimeofday (&newcall_ID->time, NULL); memset (HA1, 0, HASHLEN); //DBG ("set call time\n"); // calculate the hash // Use md5sum { "REQ/RES:Method:from:to" } MD5Init(&Md5Ctx); // add type REQ/RES snprintf (type, sizeof(type), "%d", fl->type); // add method memcpy (method, msg->first_line.u.request.method.s, msg->first_line.u.request.method.len); // add from cscf_get_from_uri (msg, &from); //DBG ("From 'uri': %.*s\n", from.len, from.s); // add to cscf_get_to_uri (msg, &to); //DBG ("To 'uri': %.*s\n", to.len, to.s); // put it together snprintf (string, sizeof(string), "%s:%s:%.*s:%.*s", type, method, from.len, from.s, to.len, to.s); LOG (L_INFO, "Calculated ID for \"%s\"\n", string); MD5Update(&Md5Ctx, string, strlen(string)); MD5Final(HA1, &Md5Ctx); memcpy (newcall_ID->id, HA1, HASHLEN); print_hex ((void *)newcall_ID->id, (void *)newcall_ID->strid, HASHLEN); LOG (L_INFO, " is %s\n", newcall_ID->strid); return newcall_ID; }
AAAMessage *rx_send_aar(struct sip_msg *req, struct sip_msg *res, AAASession* auth, str* callid, str* ftag, str* ttag, char* direction, rx_authsessiondata_t **rx_authdata) { AAAMessage* aar = 0; AAAMessage* aaa = 0; AAA_AVP* avp = 0; char x[4]; str ip; uint16_t ip_version; /* find direction for AAR (orig/term) */ //need this to add the media component details enum dialog_direction dlg_direction = get_dialog_direction(direction); if (dlg_direction == DLG_MOBILE_UNKNOWN) { LM_DBG("Asked to send AAR for unknown direction.....Aborting...\n"); goto error; } aar = cdpb.AAACreateRequest(IMS_Rx, IMS_AAR, Flag_Proxyable, auth); LM_DBG("Created aar request...\n"); if (!aar) goto error; /*Adding AVPs*/ LM_DBG("Adding auth app id AVP...\n"); /* Add Auth-Application-Id AVP */ if (!rx_add_auth_application_id_avp(aar, IMS_Rx)) goto error; if (!rx_add_vendor_specific_application_id_group(aar, IMS_vendor_id_3GPP, IMS_Rx)) goto error; LM_DBG("Adding dest realm if not there already...\n"); /* Add Destination-Realm AVP, if not already there */ avp = cdpb.AAAFindMatchingAVP(aar, aar->avpList.head, AVP_Destination_Realm, 0, AAA_FORWARD_SEARCH); if (!avp) { str realm = rx_dest_realm; if (realm.len && !rx_add_destination_realm_avp(aar, realm)) goto error; } LM_DBG("Adding AF App identifier...\n"); /* Add AF-Application-Identifier AVP */ str af_id = {0, 0}; af_id = IMS_Serv_AVP_val; if (!rx_add_avp(aar, af_id.s, af_id.len, AVP_IMS_AF_Application_Identifier, AAA_AVP_FLAG_MANDATORY, IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__)) goto error; LM_DBG("Adding service info status...\n"); /* Add Service-Info-Status AVP, if prelimiary * by default(when absent): final status is considered*/ if (!res) { set_4bytes(x, AVP_EPC_Service_Info_Status_Preliminary_Service_Information); if (!rx_add_avp(aar, x, 4, AVP_IMS_Service_Info_Status, AAA_AVP_FLAG_MANDATORY, IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__)) goto error; } /* Add Auth lifetime AVP */LM_DBG("auth_lifetime %u\n", rx_auth_expiry); //TODO check why this is 0 all the time if (rx_auth_expiry) { set_4bytes(x, rx_auth_expiry); if (!rx_add_avp(aar, x, 4, AVP_Authorization_Lifetime, AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__)) goto error; } LM_DBG("Adding subscription id...\n"); /* Add Subscription ID AVP*/ int identifier_type = AVP_Subscription_Id_Type_SIP_URI; //we only do IMPU now //to get the SIP URI I use the dlg direction - if its mo I get the from uri from the req, if its mt I get the to uri from the req str identifier; if (dlg_direction == DLG_MOBILE_ORIGINATING) { cscf_get_from_uri(req, &identifier); } else { cscf_get_to_uri(req, &identifier); } rx_add_subscription_id_avp(aar, identifier, identifier_type); LM_DBG("Adding reservation priority...\n"); /* Add Reservation Priority AVP*/ set_4bytes(x, 0); if (!rx_add_avp(aar, x, 4, AVP_ETSI_Reservation_Priority, AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_ETSI, AVP_DUPLICATE_DATA, __FUNCTION__)) goto error; LM_DBG("Adding media component...\n"); //Note we add this AVP first as it gets the IP address which we need to create the auth session //Could and maybe should have a separate method that retrieves the IP from SDP - TODO /*---------- 2. Create and add Media-Component-Description AVP ----------*/ /* * See 3GPP TS29214 * * <Media-Component-Description> = {Media-Component-Number} * [Media-Sub-Component] * [AF-Application-Identifier] * [Media-Type] * [Max-Requested-Bandwidth-UL] * [Max-Requested-Bandwidth-DL] * [Flow-Status] * [Reservation-Priority] (Not used yet) * [RS-Bandwidth] * [RR-Bandwidth] * *[Codec-Data] */ add_media_components(aar, req, res, dlg_direction, &ip, &ip_version); LM_DBG("Adding framed ip address [%.*s]\n", ip.len, ip.s); /* Add Framed IP address AVP*/ if (!rx_add_framed_ip_avp(&aar->avpList, ip, ip_version)) { LM_ERR("Unable to add framed IP AVP\n"); goto error; } LM_DBG("Unlocking AAA session...\n"); if (auth) cdpb.AAASessionsUnlock(auth->hash); LM_DBG("sending AAR to PCRF\n"); if (rx_forced_peer.len) aaa = cdpb.AAASendRecvMessageToPeer(aar, &rx_forced_peer); else aaa = cdpb.AAASendRecvMessage(aar); return aaa; error: LM_ERR("unexpected error\n"); if (aar) cdpb.AAAFreeMessage(&aar); if (auth) { cdpb.AAASessionsUnlock(auth->hash); cdpb.AAADropAuthSession(auth); auth = 0; } return NULL; }