/**
 * 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);		
}
Пример #2
0
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;
}
Пример #3
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;	
}
Пример #4
0
/**
 * 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;

}
Пример #5
0
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;
}