コード例 #1
0
int assert_called_identity(struct sip_msg* _m, udomain_t* _d) {
	
	int ret=CSCF_RETURN_FALSE;
	str called_party_id={0,0},x={0,0};
	struct sip_msg* req;
	struct hdr_field *h=0;
		
	//get request from reply
	req = get_request_from_reply(_m);
	if (!req) {
		LM_ERR("Unable to get request from reply for REGISTER. No transaction\n");
		goto error;
	}
	
	called_party_id = cscf_get_public_identity_from_called_party_id(req, &h);
	
		
	if (!called_party_id.len){
		goto error;	
	}else{
		LM_DBG("Called Party ID from request: %.*s\n", called_party_id.len, called_party_id.s);	
		x.len = p_asserted_identity_s.len+p_asserted_identity_m.len+called_party_id.len+p_asserted_identity_e.len;
		x.s = pkg_malloc(x.len);
		if (!x.s){
			LM_ERR("P_assert_called_identity: Error allocating %d bytes\n",	x.len);
			x.len=0;
			goto error;		
		}
		x.len=0;
		STR_APPEND(x,p_asserted_identity_s);
		STR_APPEND(x,p_asserted_identity_m);
		STR_APPEND(x,called_party_id);
		STR_APPEND(x,p_asserted_identity_e);
		
		if (cscf_add_header(_m,&x,HDR_OTHER_T))
			ret = CSCF_RETURN_TRUE;
		else
		    goto error;
	}
	
	return ret;
	
error:
	ret=CSCF_RETURN_FALSE;
	return ret;
}
コード例 #2
0
/**
 * Send a CCR to the OCS based on the SIP message (INVITE ONLY)
 * @param msg - SIP message
 * @param direction - orig|term
 * @param reservation_units - units to try to reserve
 * @param reservation_units - config route to call when receiving a CCA
 * @param tindex - transaction index
 * @param tindex - transaction label
 *
 * @returns #CSCF_RETURN_BREAK if OK, #CSCF_RETURN_ERROR on error
 */
int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservation_units, str* incoming_trunk_id, str* outgoing_trunk_id,
        str* pani, cfg_action_t* action, unsigned int tindex, unsigned int tlabel) {
    str session_id = {0, 0},
    called_asserted_identity = {0, 0},
    subscription_id = {0, 0},
    asserted_identity = {0, 0};
    int subscription_id_type = AVP_EPC_Subscription_Id_Type_End_User_SIP_URI;
    AAASession* cc_acc_session = NULL;
    Ro_CCR_t * ro_ccr_data = 0;
    AAAMessage * ccr = 0;
    struct ro_session *new_session = 0;
    struct session_setup_data *ssd;
    int ret = 0;
    struct hdr_field *h = 0;
    char *p;

    int cc_event_number = 0; //According to IOT tests this should start at 0
    int cc_event_type = RO_CC_START;
    int free_called_asserted_identity = 0;

    sdp_session_cell_t* msg_sdp_session;
    sdp_stream_cell_t* msg_sdp_stream;

    int active_service_identifier;
    int active_rating_group;

    int sdp_stream_num = 0;

    LM_DBG("Sending initial CCR request (%c) for reservation_units [%d] incoming_trunk_id [%.*s] outgoing_trunk_id [%.*s]\n",
	dir==RO_ORIG_DIRECTION?'O':'T',
			reservation_units,
            incoming_trunk_id->len, incoming_trunk_id->s,
            outgoing_trunk_id->len, outgoing_trunk_id->s);

    ssd = shm_malloc(sizeof (struct session_setup_data)); // lookup structure used to load session info from cdp callback on CCA
    if (!ssd) {
        LM_ERR("no more shm mem\n");
        goto error;
    }

    //getting asserted identity
    if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
        LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
        asserted_identity = dlg->from_uri;
        if (asserted_identity.len > 0 && asserted_identity.s) {
            p=(char*)memchr(asserted_identity.s, ';',asserted_identity.len);
            if (p) 
                asserted_identity.len = (p-asserted_identity.s);
        }
    }

    //getting called asserted identity
    if ((called_asserted_identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
        LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
        called_asserted_identity = cscf_get_public_identity_from_requri(msg);
        free_called_asserted_identity = 1;
    }

    if (dir == RO_ORIG_DIRECTION) {
        subscription_id.s = asserted_identity.s;
        subscription_id.len = asserted_identity.len;

    } else if (dir == RO_TERM_DIRECTION) {
        subscription_id.s = called_asserted_identity.s;
        subscription_id.len = called_asserted_identity.len;
    } else {
        LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
        goto error;
    }

    //getting subscription id type
    if (strncasecmp(subscription_id.s, "tel:", 4) == 0) {
        subscription_id_type = Subscription_Type_MSISDN;
    } else {
        subscription_id_type = Subscription_Type_IMPU; //default is END_USER_SIP_URI
    }

    str mac = {0, 0};
    if (get_mac_avp_value(msg, &mac) != 0)
        LM_DBG(RO_MAC_AVP_NAME" was not set. Using default.");

    //by default we use voice service id and rate group
    //then we check SDP - if we find video then we use video service id and rate group
    LM_DBG("Setting default SID to %d and RG to %d for voice",
            voice_service_identifier, voice_rating_group);
    active_service_identifier = voice_service_identifier;
    active_rating_group = voice_rating_group;

    //check SDP - if there is video then set default to video, if not set it to audio
    if (parse_sdp(msg) < 0) {
        LM_ERR("Unable to parse req SDP\n");
        goto error;
    }

    msg_sdp_session = get_sdp_session(msg, 0);
    if (!msg_sdp_session) {
        LM_ERR("Missing SDP session information from rpl\n");
    } else {
        for (;;) {
            msg_sdp_stream = get_sdp_stream(msg, 0, sdp_stream_num);
            if (!msg_sdp_stream) {
                //LM_ERR("Missing SDP stream information\n");
                break;
            }

            int intportA = atoi(msg_sdp_stream->port.s);
            if (intportA != 0 && strncasecmp(msg_sdp_stream->media.s, "video", 5) == 0) {
                LM_DBG("This SDP has a video component and src ports not equal to 0 - so we set default SID to %d and RG to %d for video",
                        video_service_identifier, video_rating_group);
                active_service_identifier = video_service_identifier;
                active_rating_group = video_rating_group;
                break;
            }

            sdp_stream_num++;
        }
    }

    free_sdp((sdp_info_t**) (void*) &msg->body);

    //create a session object without auth and diameter session id - we will add this later.
    new_session = build_new_ro_session(dir, 0, 0, &session_id, &dlg->callid,
            &asserted_identity, &called_asserted_identity, &mac, dlg->h_entry, dlg->h_id,
            reservation_units, 0, active_rating_group, active_service_identifier, incoming_trunk_id, outgoing_trunk_id, pani);

    if (!new_session) {
        LM_ERR("Couldn't create new Ro Session - this is BAD!\n");
        goto error;
    }

    ssd->action = action;
    ssd->tindex = tindex;
    ssd->tlabel = tlabel;
    ssd->ro_session = new_session;

    if (!sip_create_ro_ccr_data(msg, dir, &ro_ccr_data, &cc_acc_session, asserted_identity, called_asserted_identity, subscription_id, subscription_id_type, incoming_trunk_id, outgoing_trunk_id, pani))
        goto error;

    if (!ro_ccr_data)
        goto error;

    if (!cc_acc_session)
        goto error;

    if (!(ccr = Ro_new_ccr(cc_acc_session, ro_ccr_data)))
        goto error;

    if (!Ro_add_vendor_specific_appid(ccr, IMS_vendor_id_3GPP, IMS_Ro, 0)) {
        LM_ERR("Problem adding Vendor specific ID\n");
        goto error;
    }

    if (!Ro_add_cc_request(ccr, cc_event_type, cc_event_number)) {
        LM_ERR("Problem adding CC-Request data\n");
        goto error;
    }

    if (!Ro_add_event_timestamp(ccr, time(NULL))) {
        LM_ERR("Problem adding Event-Timestamp data\n");
        goto error;
    }

    if (!Ro_add_user_equipment_info(ccr, AVP_EPC_User_Equipment_Info_Type_MAC, mac)) {
        LM_ERR("Problem adding User-Equipment data\n");
        goto error;
    }

    if (!Ro_add_subscription_id(ccr, subscription_id_type, &subscription_id)) {
        LM_ERR("Problem adding Subscription ID data\n");
        goto error;
    }
    if (!Ro_add_multiple_service_credit_Control(ccr, reservation_units, -1, active_rating_group, active_service_identifier)) {
        LM_ERR("Problem adding Multiple Service Credit Control data\n");
        goto error;
    }

    /* before we send, update our session object with CC App session ID and data */
    new_session->auth_appid = cc_acc_session->application_id;
    new_session->auth_session_type = cc_acc_session->type;
    new_session->ro_session_id.s = (char*) shm_malloc(cc_acc_session->id.len);
    if (!new_session->ro_session_id.s) {
        LM_ERR("no more shm mem\n");
        goto error;
    }

    new_session->ro_session_id.len = cc_acc_session->id.len;
    memcpy(new_session->ro_session_id.s, cc_acc_session->id.s, cc_acc_session->id.len);

    LM_DBG("new CC Ro Session ID: [%.*s] stored in shared memory address [%p]\n", cc_acc_session->id.len, cc_acc_session->id.s, new_session);

    LM_DBG("Sending CCR Diameter message.\n");
//    new_session->ccr_sent = 1;      //assume we will send successfully
    cdpb.AAASessionsUnlock(cc_acc_session->hash);

    if (ro_forced_peer.len > 0) {
        LM_DBG("Sending message with Peer\n");
        ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_initial_ccr, (void *) ssd);
    } else {
        LM_DBG("Sending message without Peer and realm is [%.*s]\n", ccr->dest_realm->data.len, ccr->dest_realm->data.s);
        ret = cdpb.AAASendMessage(ccr, resume_on_initial_ccr, (void *) ssd);
    }

    if (ret != 1) {
        LM_ERR("Failed to send Diameter CCR\n");
//        new_session->ccr_sent = 0;
        goto error;
    }

    Ro_free_CCR(ro_ccr_data);

    LM_DBG("Registering for callbacks on Dialog [%p] and charging session [%p]\n", dlg, new_session);

    //TODO: if the following fail, we should clean up the Ro session.......
    if (dlgb.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED | DLGCB_CONFIRMED, dlg_callback_received, (void*) new_session, NULL) != 0) {
        LM_CRIT("cannot register callback for dialog confirmation\n");
        goto error;
    }

    counter_inc(ims_charging_cnts_h.initial_ccrs);
    counter_inc(ims_charging_cnts_h.active_ro_sessions);

    if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri	
    return RO_RETURN_BREAK;

error:
    LM_DBG("Trying to reserve credit on initial INVITE failed.\n");

    if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri	
    Ro_free_CCR(ro_ccr_data);
    if (cc_acc_session) {
        cdpb.AAASessionsUnlock(cc_acc_session->hash);
        cdpb.AAADropSession(cc_acc_session);
    }

    if (ssd)
        shm_free(ssd);

	    return RO_RETURN_ERROR;
}
コード例 #3
0
ファイル: mod.c プロジェクト: AndreyRybkin/kamailio
static int w_ro_ccr(struct sip_msg *msg, char* c_route_name, char* c_direction, char* c_charge_type, char* c_unit_type, int reservation_units, char* c_trunk_id) {
	/* PSEUDOCODE/NOTES
	 * 1. What mode are we in - terminating or originating
	 * 2. check request type - 	IEC - Immediate Event Charging
	 * 							ECUR - Event Charging with Unit Reservation
	 * 							SCUR - Session Charging with Unit Reservation
	 * 3. probably only do SCUR in this module for now - can see event based charging in another component instead (AS for SMS for example, etc)
	 * 4. Check a dialog exists for call, if not we fail
	 * 5. make sure we dont already have an Ro Session for this dialog
	 * 6. create new Ro Session
	 * 7. register for DLG callback passing new Ro session as parameter - (if dlg torn down we know which Ro session it is associated with)
	 *
	 *
	 */
	int ret = RO_RETURN_TRUE;
	int dir = 0;
	str identity = {0, 0},
		contact = {0, 0};
	struct hdr_field *h=0;
	
	cfg_action_t* cfg_action;
	tm_cell_t *t;
	unsigned int tindex = 0,
				 tlabel = 0;
	struct impu_data *impu_data;
	char *p;
	struct dlg_cell* dlg;
	unsigned int len;
	struct ro_session *ro_session = 0;
	int free_contact = 0;
	
	str s_route_name, s_direction, s_charge_type, s_unit_type, s_trunk_id;
	
	if (get_str_fparam(&s_route_name, msg, (fparam_t*) c_route_name) < 0) {
	    LM_ERR("failed to get s_route_name\n");
	    return RO_RETURN_ERROR;
	}
	if (get_str_fparam(&s_direction, msg, (fparam_t*) c_direction) < 0) {
	    LM_ERR("failed to get s_direction\n");
	    return RO_RETURN_ERROR;
	}
	if (get_str_fparam(&s_charge_type, msg, (fparam_t*) c_charge_type) < 0) {
	    LM_ERR("failed to get s_charge_type\n");
	    return RO_RETURN_ERROR;
	}
	if (get_str_fparam(&s_unit_type, msg, (fparam_t*) c_unit_type) < 0) {
	    LM_ERR("failed to get s_unit_type\n");
	    return RO_RETURN_ERROR;
	}
	if (get_str_fparam(&s_trunk_id, msg, (fparam_t*) c_trunk_id) < 0) {
	    LM_ERR("failed to get s_trunk_id\n");
	    return RO_RETURN_ERROR;
	}
	
	LM_DBG("Ro CCR initiated: direction:%.*s, charge_type:%.*s, unit_type:%.*s, reservation_units:%i, route_name:%.*s, trunk_id:%.*s\n",
			s_direction.len, s_direction.s,
			s_charge_type.len, s_charge_type.s,
			s_unit_type.len, s_unit_type.s,
			reservation_units,
			s_route_name.len, s_route_name.s,
			s_trunk_id.len, s_trunk_id.s);
	

	if (msg->first_line.type != SIP_REQUEST) {
	    LM_ERR("Ro_CCR() called from SIP reply.");
	    return RO_RETURN_ERROR;;
	}
	
	//make sure we can get the dialog! if not, we can't continue
	
	dlg = dlgb.get_dlg(msg);
	if (!dlg) {
		LM_ERR("Unable to find dialog and cannot do Ro charging without it\n");
		return RO_RETURN_ERROR;
	}
	
	dir = get_direction_as_int(&s_direction);
	
	if (dir == RO_ORIG_DIRECTION) {
		//get caller IMPU from asserted identity
		if ((identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
			LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
			identity = dlg->from_uri;
		}
		//get caller contact from contact header - if not present then skip this
		if ((contact = cscf_get_contact(msg)).len == 0) {
		    LM_WARN("Can not get contact from message - will not get callbacks if this IMPU is removed to terminate call");
			goto send_ccr;
		}
		
	} else if (dir == RO_TERM_DIRECTION){
		//get callee IMPU from called part id - if not present then skip this
		if ((identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
			LM_WARN("No P-Called-Identity hdr found - will not get callbacks if this IMPU is removed to terminate call");
			goto send_ccr;
		}
		//get callee contact from request URI
		contact = cscf_get_contact_from_requri(msg);
		free_contact = 1;
	    
	} else {
	    LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
	    ret = RO_RETURN_ERROR;
	    goto done;
	}
	
	LM_DBG("IMPU data to pass to usrloc:  contact <%.*s> identity <%.*s>\n", contact.len, contact.s, identity.len, identity.s);
	
	//create impu_data_parcel
	len = identity.len + contact.len +  sizeof (struct impu_data);
	impu_data = (struct impu_data*) shm_malloc(len);
	if (!impu_data) {
	    LM_ERR("Unable to allocate memory for impu_data, trying to send CCR\n");
	    ret = RO_RETURN_ERROR;
	    goto done;
	}
	memset(impu_data, 0, len);
	
	p = (char*) (impu_data + 1);
	impu_data->identity.s = p;
	impu_data->identity.len = identity.len;
	memcpy(p, identity.s, identity.len);
	p += identity.len;

	impu_data->contact.s = p;
	impu_data->contact.len = contact.len;
	memcpy(p, contact.s, contact.len);
	p += contact.len;
	
	if (p != (((char*) impu_data) + len)) {
	    LM_ERR("buffer overflow creating impu data, trying to send CCR\n");
	    shm_free(impu_data);
	    ret = RO_RETURN_ERROR;
	    goto done;
	}
	
	
	//reg for callbacks on confirmed and terminated
	if (dlgb.register_dlgcb(dlg, /* DLGCB_RESPONSE_FWDED */ DLGCB_CONFIRMED, add_dlg_data_to_contact, (void*)impu_data ,NULL ) != 0) {
	    LM_CRIT("cannot register callback for dialog confirmation\n");
	    ret = RO_RETURN_ERROR;
	    goto done;
	}

	if (dlgb.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED /*| DLGCB_DESTROY */, remove_dlg_data_from_contact, (void*)impu_data, NULL ) != 0) {
	    LM_CRIT("cannot register callback for dialog termination\n");
	    ret = RO_RETURN_ERROR;
	    goto done;
	}
	
send_ccr:

	//check if we need to send_ccr - 
	//we get the ro_session based on dlg->h_id and dlg->h_entry and direction 0 (so get any ro_session)
	//if it already exists then we go to done
	if (single_ro_session_per_dialog && (ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
	    LM_DBG("single_ro_session_per_dialog = 1 and ro_session already exists for this dialog -so we don't need to send another one\n");
	    unref_ro_session(ro_session,1);//for the lookup ro session ref
	    goto done;
	}
	
	LM_DBG("Looking for route block [%.*s]\n", s_route_name.len, s_route_name.s);

	int ri = route_get(&main_rt, s_route_name.s);
	if (ri < 0) {
		LM_ERR("unable to find route block [%.*s]\n", s_route_name.len, s_route_name.s);
		ret = RO_RETURN_ERROR;
		goto done;
	}
	
	cfg_action = main_rt.rlist[ri];
	if (!cfg_action) {
		LM_ERR("empty action lists in route block [%.*s]\n", s_route_name.len, s_route_name.s);
		ret = RO_RETURN_ERROR;
		goto done;
	}

	//before we send lets suspend the transaction
	t = tmb.t_gett();
	if (t == NULL || t == T_UNDEFINED) {
		if (tmb.t_newtran(msg) < 0) {
			LM_ERR("cannot create the transaction for CCR async\n");
			ret = RO_RETURN_ERROR;
			goto done;
		}
		t = tmb.t_gett();
		if (t == NULL || t == T_UNDEFINED) {
			LM_ERR("cannot lookup the transaction\n");
			ret = RO_RETURN_ERROR;
			goto done;
		}
	}

	LM_DBG("Suspending SIP TM transaction\n");
	if (tmb.t_suspend(msg, &tindex, &tlabel) < 0) {
		LM_ERR("failed to suspend the TM processing\n");
		ret =  RO_RETURN_ERROR;
		goto done;
	}
	
	ret = Ro_Send_CCR(msg, dlg, dir, &s_charge_type, &s_unit_type, reservation_units, &s_trunk_id, cfg_action, tindex, tlabel);
	
	if(ret < 0){
	    LM_ERR("Failed to send CCR\n");
		tmb.t_cancel_suspend(tindex, tlabel);
	}
    
done:
	if(free_contact)  shm_free(contact.s);// shm_malloc in cscf_get_public_identity_from_requri	
	return ret;
}