Beispiel #1
0
void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
{
	struct tmcb_params params;
	struct tm_callback    *cbp;
	struct usr_avp **backup;
	struct cell *trans_backup = get_t();

	params.req = req;
	params.rpl = 0;
	params.code = code;
	params.extra1 = tmcb_extra1;
	params.extra2 = tmcb_extra2;

	if (req_in_tmcb_hl->first==0)
		return;

	backup = set_avp_list( &trans->user_avps );
	for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next)  {
		LM_DBG("trans=%p, callback type %d, id %d entered\n",
			trans, cbp->types, cbp->id );
		params.param = &(cbp->param);
		cbp->callback( trans, cbp->types, &params );
	}
	set_avp_list( backup );
	tmcb_extra1 = tmcb_extra2 = 0;
	set_t(trans_backup);
}
Beispiel #2
0
/*if msg is set -> it will fake the env. vars conforming with the msg; if NULL
 * the env. will be restore to original */
static inline void faked_env( struct cell *t,struct sip_msg *msg)
{
	static struct cell *backup_t;
	static struct usr_avp **backup_list;
	static struct socket_info* backup_si;
	static int backup_route_type;

	if (msg) {
		swap_route_type( backup_route_type, FAILURE_ROUTE);
		/* tm actions look in beginning whether transaction is
		 * set -- whether we are called from a reply-processing 
		 * or a timer process, we need to set current transaction;
		 * otherwise the actions would attempt to look the transaction
		 * up (unnecessary overhead, refcounting)
		 */
		/* backup */
		backup_t = get_t();
		/* fake transaction */
		set_t(t);
		/* make available the avp list from transaction */
		backup_list = set_avp_list( &t->user_avps );
		/* set default send address to the saved value */
		backup_si = bind_address;
		bind_address = t->uac[0].request.dst.send_sock;
	} else {
		/* restore original environment */
		set_t(backup_t);
		set_route_type( backup_route_type );
		/* restore original avp list */
		set_avp_list( backup_list );
		bind_address = backup_si;
	}
}
Beispiel #3
0
void run_trans_callbacks( int type , struct cell *trans,
						struct sip_msg *req, struct sip_msg *rpl, int code )
{
	struct tmcb_params params;
	struct tm_callback    *cbp;
	struct usr_avp **backup;
	struct cell *trans_backup = get_t();

	params.req = req;
	params.rpl = rpl;
	params.code = code;
	params.extra1 = tmcb_extra1;
	params.extra2 = tmcb_extra2;

	if (trans->tmcb_hl.first==0 || ((trans->tmcb_hl.reg_types)&type)==0 )
		return;

	backup = set_avp_list( &trans->user_avps );
	for (cbp=trans->tmcb_hl.first; cbp; cbp=cbp->next)  {
		if ( (cbp->types)&type ) {
			LM_DBG("trans=%p, callback type %d, id %d entered\n",
				trans, type, cbp->id );
			params.param = &(cbp->param);
			cbp->callback( trans, type, &params );
		}
	}
	/* env cleanup */
	set_avp_list( backup );
	tmcb_extra1 = tmcb_extra2 = 0;
	set_t(trans_backup);
}
Beispiel #4
0
int evi_raise_event(event_id_t id, evi_params_t* params)
{
	int status;
	struct sip_msg* req= NULL;
	struct usr_avp *event_avps = 0;
	struct usr_avp **bak_avps = 0;

	/*
	 * because these might be nested, a different message has
	 * to be generated each time
	 */
	req = (struct sip_msg*)pkg_malloc(sizeof(struct sip_msg));
	if(req == NULL)
	{
		LM_ERR("No more memory\n");
		return -1;
	}
	memset(req, 0, sizeof(struct sip_msg));
	
	req->first_line.type = SIP_REQUEST;
	req->first_line.u.request.method.s= "DUMMY";
	req->first_line.u.request.method.len= 5;
	req->first_line.u.request.uri.s= "sip:[email protected]";
	req->first_line.u.request.uri.len= 19;
	
	bak_avps = set_avp_list(&event_avps);

	status = evi_raise_event_msg(req, id, params);

	/* clean whatever extra structures were added by script functions */
	free_sip_msg(req);
	pkg_free(req);

	/* remove all avps added */
	destroy_avp_list(&event_avps);
	set_avp_list(bak_avps);

	return status;
}
static int lookup_domain(struct sip_msg* msg, char* flags, char* fp)
{
    str domain, tmp;
    domain_t* d;
    unsigned int track;
    int ret = -1;
    
    track = 0;
    
    if (get_str_fparam(&domain, msg, (fparam_t*)fp) != 0) {
	ERR("Cannot get domain name to lookup\n");
	return -1;
    }
    
    tmp.s = pkg_malloc(domain.len);
    if (!tmp.s) {
	ERR("No memory left\n");
	return -1;
    }
    memcpy(tmp.s, domain.s, domain.len);
    tmp.len = domain.len;
    strlower(&tmp);

    if (db_mode) {
	if (hash_lookup(&d, *active_hash, &tmp) == 1) {
	    set_avp_list((unsigned long)flags, &d->attrs);
	    ret = 1;
	}
    } else {
	if (db_load_domain(&d, (unsigned long)flags, &tmp) == 0) {
	    set_avp_list((unsigned long)flags, &d->attrs);
	    ret = 1;
	}
    }

    pkg_free(tmp.s);
    return ret;
}
Beispiel #6
0
void async_aar_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) {
    struct cell *t = 0;
    unsigned int cdp_result;
    int result = CSCF_RETURN_ERROR;
    
    LM_DBG("Received AAR callback\n");
    saved_transaction_t* data = (saved_transaction_t*) param;

    LM_DBG("received AAA answer");

    if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
        LM_ERR("t_continue: transaction not found\n");
        goto error;
    } else {
        LM_DBG("t_continue: transaction found\n");
    }
    //we have T, lets restore our state (esp. for AVPs)
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    if (is_timeout != 0) {
        LM_ERR("Error timeout when sending AAR message via CDP\n");
        counter_inc(ims_qos_cnts_h.media_aar_timeouts);
        goto error;
    }
    if (!aaa) {
        LM_ERR("Error sending message via CDP\n");
        goto error;
    }

    counter_inc(ims_qos_cnts_h.media_aars);
    counter_add(ims_qos_cnts_h.media_aar_response_time, elapsed_msecs);
    counter_inc(ims_qos_cnts_h.media_aar_replies_received);

    /* Process the response to AAR, retrieving result code and associated Rx session ID */
    if (rx_process_aaa(aaa, &cdp_result) < 0) {
        LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s);
        goto error;
    }

    if (cdp_result >= 2000 && cdp_result < 3000) {
        LM_DBG("Success, received code: [%i] from PCRF for AAR request\n", cdp_result);
	counter_inc(ims_qos_cnts_h.successful_media_aars);
	
	LM_DBG("Auth session ID [%.*s]", aaa->sessionId->data.len, aaa->sessionId->data.s);

	if(!data->aar_update) {
	    LM_DBG("This is an AAA response to an initial AAR");
	    counter_inc(ims_qos_cnts_h.active_media_rx_sessions);
	    
	    str * passed_rx_session_id = shm_malloc(sizeof (struct _str));
	    passed_rx_session_id->s = 0;
	    passed_rx_session_id->len = 0;
	    STR_SHM_DUP(*passed_rx_session_id, aaa->sessionId->data, "cb_passed_rx_session_id");
	    LM_DBG("passed rx session id [%.*s]", passed_rx_session_id->len, passed_rx_session_id->s);

	    dlgb.register_dlgcb_nodlg(&data->callid, &data->ftag, &data->ttag, DLGCB_TERMINATED | DLGCB_DESTROY | DLGCB_EXPIRED | DLGCB_RESPONSE_WITHIN | DLGCB_CONFIRMED | DLGCB_FAILED, callback_dialog, (void*) (passed_rx_session_id), free_dialog_data);
	} 
        result = CSCF_RETURN_TRUE;
    } else {
        LM_DBG("Received negative reply from PCRF for AAR Request\n");
	counter_inc(ims_qos_cnts_h.failed_media_aars);
        //we don't free rx_authdata_p here - it is free-ed when the CDP session expires
        goto error; // if its not a success then that means i want to reject this call!
    }

    //set success response code AVP
    create_return_code(result);
    goto done;

out_of_memory:
    error :
            //set failure response code
            create_return_code(result);

done:
    if (t) tmb.unref_cell(t);
    //free memory
    if (aaa)
        cdpb.AAAFreeMessage(&aaa);

    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_global_data(data);
}
Beispiel #7
0
/* function triggered from reactor in order to continue the processing
 */
int t_resume_async(int *fd, void *param)
{
    static struct sip_msg faked_req;
    static struct ua_client uac;
    async_ctx *ctx = (async_ctx *)param;
    struct cell *backup_t;
    struct cell *backup_cancelled_t;
    struct cell *backup_e2eack_t;
    struct usr_avp **backup_list;
    struct socket_info* backup_si;
    struct cell *t= ctx->t;
    int route;

    LM_DBG("resuming on fd %d, transaction %p \n",*fd, t);

    if (current_processing_ctx) {
        LM_CRIT("BUG - a context already set!\n");
        abort();
    }

    /* prepare for resume route */
    uac.br_flags = getb0flags( t->uas.request ) ;
    uac.uri = *GET_RURI( t->uas.request );
    if (!fake_req( &faked_req /* the fake msg to be built*/,
                   t->uas.request, /* the template msg saved in transaction */
                   &t->uas, /*the UAS side of the transaction*/
                   &uac, /* the fake UAC */
                   1 /* copy dst_uri too */)
       ) {
        LM_ERR("fake_req failed\n");
        return 0;
    }

    /* enviroment setting */
    current_processing_ctx = ctx->msg_ctx;
    backup_t = get_t();
    backup_e2eack_t = get_e2eack_t();
    backup_cancelled_t = get_cancelled_t();
    /* fake transaction */
    set_t( t );
    set_cancelled_t(ctx->cancelled_t);
    set_e2eack_t(ctx->e2eack_t);
    reset_kr();
    set_kr(ctx->kr);
    /* make available the avp list from transaction */
    backup_list = set_avp_list( &t->user_avps );
    /* set default send address to the saved value */
    backup_si = bind_address;
    bind_address = t->uac[0].request.dst.send_sock;

    async_status = ASYNC_DONE; /* assume default status as done */
    /* call the resume function in order to read and handle data */
    return_code = ctx->resume_f( *fd, &faked_req, ctx->resume_param );
    if (async_status==ASYNC_CONTINUE) {
        /* do not run the resume route */
        goto restore;
    } else if (async_status==ASYNC_CHANGE_FD) {
        if (return_code<0) {
            LM_ERR("ASYNC_CHANGE_FD: given file descriptor shall be positive!\n");
            goto restore;
        } else if (return_code > 0 && return_code == *fd) {
            /*trying to add the same fd; shall continue*/
            LM_CRIT("You are trying to replace the old fd with the same fd!"
                    "Will act as in ASYNC_CONTINUE!\n");
            goto restore;
        }

        /* remove the old fd from the reactor */
        reactor_del_reader( *fd, -1, IO_FD_CLOSING);
        *fd=return_code;

        /* insert the new fd inside the reactor */
        if (reactor_add_reader( *fd, F_SCRIPT_ASYNC, RCT_PRIO_ASYNC, (void*)ctx)<0 ) {
            LM_ERR("failed to add async FD to reactor -> act in sync mode\n");
            do {
                return_code = ctx->resume_f( *fd, &faked_req, ctx->resume_param );
                if (async_status == ASYNC_CHANGE_FD)
                    *fd=return_code;
            } while(async_status==ASYNC_CONTINUE||async_status==ASYNC_CHANGE_FD);
            goto route;
        }

        /* changed fd; now restore old state */
        goto restore;
    }

    /* remove from reactor, we are done */
    reactor_del_reader( *fd, -1, IO_FD_CLOSING);

route:
    if (async_status == ASYNC_DONE_CLOSE_FD)
        close(*fd);

    /* run the resume_route (some type as the original one) */
    swap_route_type(route, ctx->route_type);
    run_resume_route( ctx->resume_route, &faked_req);
    set_route_type(route);

    /* no need for the context anymore */
    shm_free(ctx);

    /* free also the processing ctx if still set
     * NOTE: it may become null if inside the run_resume_route
     * another async jump was made (and context attached again
     * to transaction) */
    if (current_processing_ctx) {
        context_destroy(CONTEXT_GLOBAL, current_processing_ctx);
        pkg_free(current_processing_ctx);
    }

restore:
    /* restore original environment */
    set_t(backup_t);
    set_cancelled_t(backup_cancelled_t);
    set_e2eack_t(backup_e2eack_t);
    /* restore original avp list */
    set_avp_list( backup_list );
    bind_address = backup_si;

    free_faked_req( &faked_req, t);
    current_processing_ctx = NULL;

    return 0;
}
Beispiel #8
0
void async_cdp_uar_callback(int is_timeout, void *param, AAAMessage *uaa, long elapsed_msecs) {
    struct run_act_ctx ra_ctx;
    str server_name;
    int *m_capab = 0, m_capab_cnt = 0;
    int *o_capab = 0, o_capab_cnt = 0;
    str *p_server_names = 0;
    int p_server_names_cnt = 0;
    int rc = -1, experimental_rc = -1;
    saved_uar_transaction_t* data = (saved_uar_transaction_t*) param;
    struct cell *t = 0;
    int result = CSCF_RETURN_TRUE;
    scscf_entry *list = 0;

    if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
        LM_ERR("ERROR: t_continue: transaction not found\n");
        //result = CSCF_RETURN_ERROR;//not needed we set by default to error!
        goto error;
    }

    if (is_timeout != 0) {
        LM_ERR("Error timeout when  sending message via CDP\n");
        update_stat(stat_uar_timeouts, 1);
        goto error;
    }

    //update stats on response time
    update_stat(uar_replies_received, 1);
    update_stat(uar_replies_response_time, elapsed_msecs);

    if (!uaa) {
        LM_ERR("Error sending message via CDP\n");
        //result = CSCF_RETURN_ERROR;//not needed we set by default to error!
        goto error;
    }

    server_name = cxdx_get_server_name(uaa);
    if (!server_name.len) {
        cxdx_get_capabilities(uaa, &m_capab, &m_capab_cnt, &o_capab,
                &o_capab_cnt, &p_server_names, &p_server_names_cnt);
    }

    cxdx_get_result_code(uaa, &rc);
    cxdx_get_experimental_result_code(uaa, &experimental_rc);

    if (rc && !experimental_rc) {
        LM_ERR("No result code or experimental result code - responding 480\n");
        cscf_reply_transactional_async(t, t->uas.request, 480, MSG_480_DIAMETER_MISSING_AVP);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    switch (rc) {
        case -1:
            switch (experimental_rc) {
                case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN:
                    /* Check, if route is set: */
                    if (route_uar_user_unknown_no >= 0) {
                        /* exec routing script */
                        init_run_actions_ctx(&ra_ctx);
                        if (run_actions(&ra_ctx, main_rt.rlist[route_uar_user_unknown_no], t->uas.request) < 0) {
                            LM_DBG("ims_icscf: error while trying script\n");
                        }
                    } else {
                        cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_USER_UNKNOWN);
                    }
                    LM_ERR("RC_IMS_DIAMETER_ERROR_USER_UNKNOWN\n");
                    result = CSCF_RETURN_FALSE;
                    goto done;
                case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH:
                    LM_ERR("RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH returning 403\n");
                    cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_IDENTITIES_DONT_MATCH);
                    result = CSCF_RETURN_FALSE;
                    goto done;
                case RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED:
                    LM_ERR("RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED returning 403\n");
                    cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_ROAMING_NOT_ALLOWED);
                    result = CSCF_RETURN_FALSE;
                    goto done;
                case RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED:
                    LM_ERR("RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED returning 403\n");
                    cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_IDENTITY_NOT_REGISTERED);
                    result = CSCF_RETURN_FALSE;
                    goto done;
                case RC_IMS_DIAMETER_FIRST_REGISTRATION:
                    goto success;
                case RC_IMS_DIAMETER_SUBSEQUENT_REGISTRATION:
                    goto success;
                case RC_IMS_DIAMETER_SERVER_SELECTION:
                    goto success;

                default:
                    LM_ERR("MSG_403_UNKOWN_EXPERIMENTAL_RC returning 500\n");
                    cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_UNKOWN_EXPERIMENTAL_RC);
                    result = CSCF_RETURN_FALSE;
                    goto done;
            }
            break;

        case AAA_AUTHORIZATION_REJECTED:
            LM_ERR("AAA_AUTHORIZATION_REJECTED returning 403\n");
            cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_AUTHORIZATION_REJECTED);
            result = CSCF_RETURN_FALSE;
            goto done;
        case AAA_UNABLE_TO_COMPLY:
            LM_ERR("AAA_UNABLE_TO_COMPLY returning 403\n");
            cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_UNABLE_TO_COMPLY);
            result = CSCF_RETURN_FALSE;
            goto done;

        case AAA_SUCCESS:
            goto success;

        default:
            LM_ERR("MSG_403_UNKOWN_RC returning 403\n");
            cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_UNKOWN_RC);
            result = CSCF_RETURN_FALSE;
            goto done;
    }

success:
    LM_DBG("successful UAA response\n");
    list = I_get_capab_ordered(server_name, m_capab, m_capab_cnt, o_capab, o_capab_cnt, p_server_names, p_server_names_cnt, 0);

    if (!list) {
        LM_ERR("Empty capability list returning 600\n");
        cscf_reply_transactional_async(t, t->uas.request, 600, MSG_600_EMPTY_LIST);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    if (!data->callid.len || !add_scscf_list(data->callid, list)) {
        LM_ERR("Error saving capability list 500\n");
        cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_ERROR_SAVING_LIST);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    result = CSCF_RETURN_TRUE;

done:
	//free capabilities if they exist
	if (m_capab) shm_free(m_capab);
	if (o_capab) shm_free(o_capab);
	if (p_server_names) shm_free(p_server_names);

    LM_DBG("DBG:UAR Async CDP callback: ... Done resuming transaction\n");
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    create_uaa_return_code(result);

    if (t)tmb.unref_cell(t);
    //free memory
    if (uaa) cdpb.AAAFreeMessage(&uaa);

    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_uar_transaction_data(data);
    return;

error:
    if (t)tmb.unref_cell(t);
    //free memory
    if (uaa) cdpb.AAAFreeMessage(&uaa);

    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_uar_transaction_data(data);


}
Beispiel #9
0
void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) {
    struct cell *t = 0;
    pcontact_t* pcontact;
    unsigned int cdp_result;
    struct pcontact_info ci;
    udomain_t* domain_t;
    int finalReply = 0;
    AAASession *auth = 0;
    rx_authsessiondata_t* p_session_data = 0;
    int result = CSCF_RETURN_ERROR;
    pcontact_info_t contact_info;

    LM_DBG("Received AAR callback\n");
    saved_transaction_local_t* local_data = (saved_transaction_local_t*) param;
    saved_transaction_t* data = local_data->global_data;
    domain_t = data->domain;

    int is_rereg = local_data->is_rereg;

    //before we do anything else, lets decrement the reference counter on replies
    lock_get(data->lock);
    data->answers_not_received--;
    if (data->answers_not_received <= 0) {
        finalReply = 1;
    }
    if (data->ignore_replies) { //there was obv. a subsequent error AFTER we had sent one/more AAR's - so we can ignore these replies and just free memory
        free_saved_transaction_data(local_data);
        if (finalReply) {
            free_saved_transaction_global_data(data);
        }
        return;
    }
    lock_release(data->lock);

    LM_DBG("received answer and we are waiting for [%d] answers so far failures flag is [%d]\n", data->answers_not_received, data->failed);

    if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
        LM_ERR("t_continue: transaction not found\n");
        goto error;
    }
    //we have T, lets restore our state (esp. for AVPs)
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    if (is_timeout != 0) {
        LM_ERR("Error timeout when sending AAR message via CDP\n");
        counter_inc(ims_qos_cnts_h.registration_aar_timeouts);
        goto error;
    }
    if (!aaa) {
        LM_ERR("Error sending message via CDP\n");
        goto error;
    }

    counter_inc(ims_qos_cnts_h.registration_aars);
    counter_add(ims_qos_cnts_h.registration_aar_response_time, elapsed_msecs);
    counter_inc(ims_qos_cnts_h.registration_aar_replies_received);

    /* Process the response to AAR, retrieving result code and associated Rx session ID */
    if (rx_process_aaa(aaa, &cdp_result) < 0) {
        LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s);
        goto error;
    }

    if (cdp_result >= 2000 && cdp_result < 3000) {
        counter_inc(ims_qos_cnts_h.successful_registration_aars);
	if (is_rereg) {
            LM_DBG("this is a re-registration, therefore we don't need to do anything except know that the the subscription was successful\n");
            result = CSCF_RETURN_TRUE;
            create_return_code(result);
            goto done;
        }
	//need to set Rx auth data to say this session has been successfully opened
	//This is used elsewhere to prevent acting on termination events when the session has not been opened
	//getting auth session
	auth = cdpb.AAAGetAuthSession(aaa->sessionId->data);
	if (!auth) {
	    LM_DBG("Could not get Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s);
	    goto error;
	}
	//getting session data
	p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data;
	if (!p_session_data) {
	    LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s);
	    if (auth) cdpb.AAASessionsUnlock(auth->hash);
	    goto error;
	}
	p_session_data->session_has_been_opened = 1;
	counter_inc(ims_qos_cnts_h.active_registration_rx_sessions);
	
	if (auth) cdpb.AAASessionsUnlock(auth->hash);
	
	
        LM_DBG("Success, received code: [%i] from PCRF for AAR request (contact: [%.*s]), (auth session id: %.*s)\n",
                cdp_result, local_data->contact.len, local_data->contact.s,
                local_data->auth_session_id.len, local_data->auth_session_id.s);
        LM_DBG("Registering for Usrloc callbacks on DELETE\n");

        ul.lock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto);
        
        contact_info.received_host = local_data->recv_host;
        contact_info.received_port = local_data->recv_port;
        contact_info.received_proto = local_data->recv_proto;
        contact_info.searchflag = (1 << SEARCH_RECEIVED);
        
        
        contact_info.aor = local_data->contact;
        contact_info.via_host = local_data->via_host;
        contact_info.via_port = local_data->via_port;
        contact_info.via_prot = local_data->via_proto;
        
        if (ul.get_pcontact(domain_t, &contact_info, &pcontact) != 0) {
            LM_ERR("Shouldn't get here, can't find contact....\n");
            ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto);
            goto error;
        }

        //at this point we have the contact
        /*set the contact state to say we have succesfully done ARR for register and that we dont need to do it again
         * for the duration of the registration.
         * */
        if (ul.update_rx_regsession(domain_t, &local_data->auth_session_id, pcontact) != 0) {
            LM_ERR("unable to update pcontact......\n");
            ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto);
            goto error;
        }
        memset(&ci, 0, sizeof (struct pcontact_info));
        ci.reg_state = PCONTACT_REG_PENDING_AAR;
        ci.num_service_routes = 0;
        ci.num_public_ids = 0;
        LM_DBG("impu: [%.*s] updating status to PCONTACT_REG_PENDING\n", pcontact->aor.len, pcontact->aor.s);
        ul.update_pcontact(domain_t, &ci, pcontact);
        //register for callbacks on contact
        ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE,
                callback_pcscf_contact_cb, NULL);
        ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto);
        result = CSCF_RETURN_TRUE;
    } else {
        LM_DBG("Received negative reply from PCRF for AAR Request\n");
	counter_inc(ims_qos_cnts_h.failed_registration_aars);
        result = CSCF_RETURN_FALSE;
        goto error;
    }

    //set success response code AVP
    create_return_code(result);
    goto done;

error:
    //set failure response code
    create_return_code(result);

done:
    if (t) tmb.unref_cell(t);
    //free memory
    if (aaa)
        cdpb.AAAFreeMessage(&aaa);

    if (finalReply) {
        tmb.t_continue(data->tindex, data->tlabel, data->act);
        free_saved_transaction_global_data(data);
    }
    free_saved_transaction_data(local_data);
}
Beispiel #10
0
static inline int pre_print_uac_request( struct cell *t, int branch, 
		struct sip_msg *request)
{
	int backup_route_type;
	struct usr_avp **backup_list;
	char *p;

	/* ... we calculate branch ... */
	if (!t_calc_branch(t, branch, request->add_to_branch_s,
			&request->add_to_branch_len ))
	{
		LOG(L_ERR, "ERROR:pre_print_uac_request: branch computation failed\n");
		goto error;
	}

	/* from now on, flag all new lumps with LUMPFLAG_BRANCH flag in order to
	 * be able to remove them later --bogdan */
	set_init_lump_flags(LUMPFLAG_BRANCH);

	/********** run route & callback ************/

	/* run branch route, if any; run it before RURI's DNS lookup 
	 * to allow to be changed --bogdan */
	if (t->on_branch) {
		/* need to pkg_malloc the dst_uri */
		if ( request->dst_uri.len ) {
			if ( (p=pkg_malloc(request->dst_uri.len))==0 ) {
				LOG(L_ERR,"ERROR:tm:pre_print_uac_request: no more pkg mem\n");
				ser_error=E_OUT_OF_MEM;
				goto error;
			}
			memcpy( p, request->dst_uri.s, request->dst_uri.len);
			request->dst_uri.s = p;
		}
		/* need to pkg_malloc the new_uri */
		if ( (p=pkg_malloc(request->new_uri.len))==0 ) {
			LOG(L_ERR,"ERROR:tm:pre_print_uac_request: no more pkg mem\n");
			ser_error=E_OUT_OF_MEM;
			goto error;
		}
		memcpy( p, request->new_uri.s, request->new_uri.len);
		request->new_uri.s = p;
		/* make available the avp list from transaction */
		backup_list = set_avp_list( &t->user_avps );
		/* run branch route */
		swap_route_type( backup_route_type, BRANCH_ROUTE);
		if (run_actions(branch_rlist[t->on_branch], request)==0 &&
		(action_flags&ACT_FL_DROP) ) {
			DBG("DEBUG:tm:pre_print_uac_request: dropping branch <%.*s>\n",
				request->dst_uri.len, request->dst_uri.s);
			goto error;
		}
		set_route_type( backup_route_type );
		/* restore original avp list */
		set_avp_list( backup_list );
	}

	/* run the specific callbacks for this transaction */
	run_trans_callbacks( TMCB_REQUEST_FWDED, t, request, 0,
			-request->REQ_METHOD);

	return 0;
error:
	return -1;
}
Beispiel #11
0
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
				transaction_cb cb, void* cbp,release_tmcb_param release_func)
{
	union sockaddr_union to_su;
	struct cell *new_cell;
	struct retr_buf *request;
	static struct sip_msg *req;
	struct usr_avp **backup;
	char *buf, *buf1;
	int buf_len, buf_len1;
	int ret, flags, sflag_bk;
	int backup_route_type;
	unsigned int hi;
	struct socket_info* send_sock;

	ret=-1;
	
	/*** added by dcm 
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error2;

	if(dialog->obp.s)
		dialog->hooks.next_hop = &dialog->obp;

	LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);

	/* calculate the socket corresponding to next hop */
	send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su,
			PROTO_NONE);
	if (send_sock==0) {
		ret=ser_error;
		LM_ERR("no socket found\n");
		goto error2;
	}
	/* if a send socket defined verify if the same protocol */
	if(dialog->send_sock) {
		if(send_sock->proto != dialog->send_sock->proto)
		{
			dialog->send_sock = send_sock;
		}
	}
	else
	{
		dialog->send_sock = send_sock;
	}

	new_cell = build_cell(0);
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LM_ERR("short of cell shmem\n");
		goto error2;
	}

	/* pass the transaction flags from dialog to transaction */
	new_cell->flags |= dialog->T_flags;

	/* add the callback the transaction for LOCAL_COMPLETED event */
	flags = TMCB_LOCAL_COMPLETED;
	/* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */
	if (pass_provisional_replies || pass_provisional(new_cell))
		flags |= TMCB_LOCAL_RESPONSE_OUT;
	if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){
		ret=E_OUT_OF_MEM;
		LM_ERR("short of tmcb shmem\n");
		goto error2;
	}

	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)
		new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->flags |= T_IS_LOCAL_FLAG;

	request = &new_cell->uac[0].request;
	request->dst.to = to_su;
	request->dst.send_sock = dialog->send_sock;
	request->dst.proto = dialog->send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len);
	if (!buf) {
		LM_ERR("failed to build message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	if (local_rlist.a) {
		LM_DBG("building sip_msg from buffer\n");
		req = buf_to_sip_msg(buf, buf_len, dialog);
		if (req==NULL) {
			LM_ERR("failed to build sip_msg from buffer");
		} else {
			/* set transaction AVP list */
			backup = set_avp_list( &new_cell->user_avps );
			/* backup script flags */
			sflag_bk = getsflags();
			/* disable parallel forking */
			set_dset_state( 0 /*disable*/);

			/* transfer current message context back to t */
			new_cell->uac[0].br_flags = req->flags;

			/* run the route */
			swap_route_type( backup_route_type, LOCAL_ROUTE);
			run_top_route( local_rlist.a, req);
			set_route_type( backup_route_type );

			set_dset_state( 1 /*enable*/);
			setsflagsval(sflag_bk);
			set_avp_list( backup );

			/* check for changes - if none, do not regenerate the buffer 
			 * we ignore any change on RURI and DSTURI and they should not
			 * be changed  -bogdan */
			if (req->new_uri.s)
				{ pkg_free(req->new_uri.s); req->new_uri.s=0; req->new_uri.len=0; }
			if (req->dst_uri.s)
				{ pkg_free(req->dst_uri.s); req->dst_uri.s=0; req->dst_uri.len=0; }

			if (req->add_rm || req->body_lumps) {
				LM_DBG("re-building the buffer (sip_msg changed) - lumps are"
					"%p %p\n",req->add_rm, req->body_lumps);
				/* build the shm buffer now */
				buf1 = build_req_buf_from_sip_req(req,(unsigned int*)&buf_len1,
					dialog->send_sock, dialog->send_sock->proto,
					MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG );
				if (!buf1) {
					LM_ERR("no more shm mem\n"); 
					/* keep original buffer */
				} else {
					shm_free(buf);
					buf = buf1;
					buf_len = buf_len1;
					/* use new buffer */
				}
			}
			free_sip_msg(req);
		}
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer.s = buf;
	request->buffer.len = buf_len;
	new_cell->nr_of_outgoings++;

	if(last_localT)
	{
		*last_localT = new_cell;
		REF_UNSAFE(new_cell);
	}

	if (SEND_BUFFER(request) == -1) {
		LM_ERR("attempt to send to '%.*s' failed\n", 
			dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	}

	if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) {
		t_release_transaction(new_cell);
	} else {
		start_retr(request);
	}


	return 1;

error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);
error2:
	return ret;
}
static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs) {
    Ro_CCA_t *ro_cca_data = NULL;
    struct cell *t = NULL;
    struct session_setup_data *ssd = (struct session_setup_data *) param;
    int error_code = RO_RETURN_ERROR;

    if (is_timeout) {
        counter_inc(ims_charging_cnts_h.ccr_timeouts);
        LM_ERR("Transaction timeout - did not get CCA\n");
        error_code = RO_RETURN_ERROR;
        goto error0;
    }

    counter_inc(ims_charging_cnts_h.ccr_replies_received);
    counter_add(ims_charging_cnts_h.ccr_response_time, elapsed_msecs);

    if (!cca) {
        LM_ERR("Error reserving credit for CCA.\n");
        error_code = RO_RETURN_ERROR;
        goto error0;
    }

    if (!ssd) {
        LM_ERR("Session lookup data is NULL.\n");
        error_code = RO_RETURN_ERROR;
        goto error0;
    }

    // we make sure the transaction exists
    if (tmb.t_lookup_ident(&t, ssd->tindex, ssd->tlabel) < 0) {
        LM_ERR("t_continue: transaction not found\n");
        error_code = RO_RETURN_ERROR;
        goto error0;
    }

    // we bring the list of AVPs of the transaction to the current context
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    ro_cca_data = Ro_parse_CCA_avps(cca);

    if (!ro_cca_data) {
        LM_ERR("Could not parse CCA message response.\n");
        error_code = RO_RETURN_ERROR;
	create_cca_result_code(0);
        goto error0;
    }
    create_cca_result_code((int)ro_cca_data->resultcode);
    if (ro_cca_data->resultcode != 2001) {
        LM_ERR("Got bad CCA result code - reservation failed");
        error_code = RO_RETURN_FALSE;
        goto error1;
    }

    LM_DBG("Valid CCA response with time chunk of [%i] and validity [%i]\n",
            ro_cca_data->mscc->granted_service_unit->cc_time,
            ro_cca_data->mscc->validity_time);

    if (ro_cca_data->mscc->granted_service_unit->cc_time <= 0) {
        LM_DBG("got zero GSU.... reservation failed");
        error_code = RO_RETURN_FALSE;
        goto error1;
    }

    ssd->ro_session->last_event_timestamp = get_current_time_micro();
    ssd->ro_session->event_type = pending;
    ssd->ro_session->reserved_secs = ro_cca_data->mscc->granted_service_unit->cc_time;
    ssd->ro_session->valid_for = ro_cca_data->mscc->validity_time;
    ssd->ro_session->is_final_allocation = 0;

    if (ro_cca_data->mscc->final_unit_action && (ro_cca_data->mscc->final_unit_action->action == 0))
        ssd->ro_session->is_final_allocation = 1;

    Ro_free_CCA(ro_cca_data);

    LM_DBG("Freeing CCA message\n");
    cdpb.AAAFreeMessage(&cca);

    link_ro_session(ssd->ro_session, 0); 

    if (ro_db_mode == DB_MODE_REALTIME) {
        ssd->ro_session->flags |= RO_SESSION_FLAG_NEW;
        if (update_ro_dbinfo(ssd->ro_session) != 0) {
            LM_ERR("Failed to update ro_session in database... continuing\n");
        };
    }

    unref_ro_session(ssd->ro_session, 1); /* release our reference */

    create_cca_return_code(RO_RETURN_TRUE);

    if (t)
        tmb.unref_cell(t);

    tmb.t_continue(ssd->tindex, ssd->tlabel, ssd->action);
    shm_free(ssd);

    counter_inc(ims_charging_cnts_h.successful_initial_ccrs);

    return;

error1:
    Ro_free_CCA(ro_cca_data);

error0:
    LM_DBG("Trying to reserve credit on initial INVITE failed on cdp callback\n");
//    counter_add(ims_charging_cnts_h.active_ro_sessions, -1); /*we bumped active on the original initial ccr sent */
    counter_inc(ims_charging_cnts_h.failed_initial_ccrs);      /* drop by one as theoretically this is failed initial ccr */
    create_cca_return_code(error_code);

    if (!is_timeout && cca) {
        cdpb.AAAFreeMessage(&cca);
    }

    if (t)
        tmb.unref_cell(t);

    tmb.t_continue(ssd->tindex, ssd->tlabel, ssd->action);
    shm_free(ssd);
}
Beispiel #13
0
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
				transaction_cb cb, void* cbp,release_tmcb_param release_func)
{
	union sockaddr_union to_su, new_to_su;
	struct cell *new_cell;
	struct cell *backup_cell;
	struct retr_buf *request;
	static struct sip_msg *req;
	struct usr_avp **backup;
	char *buf, *buf1;
	int buf_len, buf_len1;
	int ret, flags, sflag_bk;
	int backup_route_type;
	int sip_msg_len;
	unsigned int hi;
	struct socket_info *new_send_sock;
	str h_to, h_from, h_cseq, h_callid;
	struct proxy_l *proxy, *new_proxy;
	unsigned short dst_changed;

	ret=-1;

	/*** added by dcm
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error3;

	if(dialog->obp.s)
		dialog->hooks.next_hop = &dialog->obp;

	LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);

	/* calculate the socket corresponding to next hop */
	proxy = uri2proxy( dialog->hooks.next_hop,
		dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE );
	if (proxy==0)  {
		ret=E_BAD_ADDRESS;
		goto error3;
	}
	/* use the first address */
	hostent2su( &to_su,
		&proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT);

	/* check/discover the send socket */
	if (dialog->send_sock) {
		/* if already set, the protocol of send sock must have the 
		   the same type as the proto required by destination URI */
		if (proxy->proto != dialog->send_sock->proto)
			dialog->send_sock = NULL;
	}
	if (dialog->send_sock==NULL) {
		/* get the send socket */
		dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto);
		if (!dialog->send_sock) {
			LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family);
			ser_error = E_NO_SOCKET;
			goto error2;
		}
	}
	LM_DBG("sending socket is %.*s \n",
		dialog->send_sock->name.len,dialog->send_sock->name.s);


	/* ***** Create TRANSACTION and all related  ***** */
	new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/);
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LM_ERR("short of cell shmem\n");
		goto error2;
	}

	/* pass the transaction flags from dialog to transaction */
	new_cell->flags |= dialog->T_flags;

	/* add the callback the transaction for LOCAL_COMPLETED event */
	flags = TMCB_LOCAL_COMPLETED;
	/* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */
	if (pass_provisional_replies || pass_provisional(new_cell))
		flags |= TMCB_LOCAL_RESPONSE_OUT;
	if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){
		ret=E_OUT_OF_MEM;
		LM_ERR("short of tmcb shmem\n");
		goto error2;
	}

	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)
		new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->flags |= T_IS_LOCAL_FLAG;

	request = &new_cell->uac[0].request;
	if (dialog->forced_to_su.s.sa_family == AF_UNSPEC)
		request->dst.to = to_su;
	else
		request->dst.to = dialog->forced_to_su;
	request->dst.send_sock = dialog->send_sock;
	request->dst.proto = dialog->send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	/* copy AVPs into transaction */
	new_cell->user_avps = dialog->avps;
	dialog->avps = NULL;


	/* ***** Create the message buffer ***** */
	buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len);
	if (!buf) {
		LM_ERR("failed to build message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	if (local_rlist.a) {
		LM_DBG("building sip_msg from buffer\n");
		req = buf_to_sip_msg(buf, buf_len, dialog);
		if (req==NULL) {
			LM_ERR("failed to build sip_msg from buffer\n");
		} else {
			/* set this transaction as active one */
			backup_cell = get_t();
			set_t( new_cell );
			/* set transaction AVP list */
			backup = set_avp_list( &new_cell->user_avps );
			/* backup script flags */
			sflag_bk = getsflags();
			/* disable parallel forking */
			set_dset_state( 0 /*disable*/);

			/* run the route */
			swap_route_type( backup_route_type, LOCAL_ROUTE);
			run_top_route( local_rlist.a, req);
			set_route_type( backup_route_type );

			/* transfer current message context back to t */
			new_cell->uac[0].br_flags = getb0flags(req);
			/* restore the prevoius active transaction */
			set_t( backup_cell );

			set_dset_state( 1 /*enable*/);
			setsflagsval(sflag_bk);
			set_avp_list( backup );

			/* check for changes - if none, do not regenerate the buffer */
			dst_changed = 1;
			if (req->new_uri.s || req->force_send_socket!=dialog->send_sock ||
			req->dst_uri.len != dialog->hooks.next_hop->len ||
			memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) ||
			(dst_changed=0)==0 || req->add_rm || req->body_lumps){

				new_send_sock = NULL;
				/* do we also need to change the destination? */
				if (dst_changed) {
					/* calculate the socket corresponding to next hop */
					new_proxy = uri2proxy(
						req->dst_uri.s ? &(req->dst_uri) : &req->new_uri,
						PROTO_NONE );
					if (new_proxy==0)
						goto abort_update;
					/* use the first address */
					hostent2su( &new_to_su,
						&new_proxy->host, new_proxy->addr_idx,
						new_proxy->port ? new_proxy->port:SIP_PORT);
					/* get the send socket */
					new_send_sock = get_send_socket( req, &new_to_su,
						new_proxy->proto);
					if (!new_send_sock) {
						free_proxy( new_proxy );
						pkg_free( new_proxy );
						LM_ERR("no socket found for the new destination\n");
						goto abort_update;
					}
				}

				/* if interface change, we need to re-build the via */
				if (new_send_sock && new_send_sock != dialog->send_sock) {
					LM_DBG("Interface change in local route -> "
						"rebuilding via\n");
					if (!del_lump(req,req->h_via1->name.s - req->buf,
					req->h_via1->len,0)) {
						LM_ERR("Failed to remove initial via \n");
						goto abort_update;
					}

					memcpy(req->add_to_branch_s,req->via1->branch->value.s,
						req->via1->branch->value.len);
					req->add_to_branch_len = req->via1->branch->value.len;

					/* update also info about new destination and send sock */
					dialog->send_sock = new_send_sock;
					free_proxy( proxy );
					pkg_free( proxy );
					proxy = new_proxy;
					request->dst.send_sock = new_send_sock;
					request->dst.proto = new_send_sock->proto;
					request->dst.proto_reserved1 = 0;

					/* build the shm buffer now */
					set_init_lump_flags(LUMPFLAG_BRANCH);
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						new_send_sock, new_send_sock->proto,
						MSG_TRANS_SHM_FLAG);
					reset_init_lump_flags();
					del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH);

				} else {

					LM_DBG("Change in local route -> rebuilding buffer\n");
					/* build the shm buffer now */
					buf1 = build_req_buf_from_sip_req(req,
						(unsigned int*)&buf_len1,
						dialog->send_sock, dialog->send_sock->proto,
						MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG);
					/* now as it used, hide the original VIA header */
					del_lump(req,req->h_via1->name.s - req->buf,
						req->h_via1->len, 0);

				}

				if (!buf1) {
					LM_ERR("no more shm mem\n");
					/* keep original buffer */
					goto abort_update;
				}
				/* update shortcuts */
				if(!req->add_rm && !req->new_uri.s) {
					/* headers are not affected, simply tranlate */
					new_cell->from.s = new_cell->from.s - buf + buf1;
					new_cell->to.s = new_cell->to.s - buf + buf1;
					new_cell->callid.s = new_cell->callid.s - buf + buf1;
					new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1;
				} else {
					/* use heavy artilery :D */
					if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to,
					&h_cseq, &h_callid)!=0 ) {
						LM_ERR("failed to update shortcut pointers\n");
						shm_free(buf1);
						goto abort_update;
					}
					new_cell->from = h_from;
					new_cell->to = h_to;
					new_cell->callid = h_callid;
					new_cell->cseq_n = h_cseq;
				}
				/* here we rely on how build_uac_req()
				   builds the first line */
				new_cell->uac[0].uri.s = buf1 +
					req->first_line.u.request.method.len + 1;
				new_cell->uac[0].uri.len = GET_RURI(req)->len;

				/* update also info about new destination and send sock */
				if (new_send_sock)
					request->dst.to = new_to_su;

				shm_free(buf);
				buf = buf1;
				buf_len = buf_len1;
				/* use new buffer */
			} else {
				/* no changes over the message, buffer is already generated,
				   just hide the original VIA for potential further branches */
				del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0);
			}
abort_update:
			/* save the SIP message into transaction */
			new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1);
			if (new_cell->uas.request==NULL) {
				/* reset any T triggering */
				new_cell->on_negative = 0;
				new_cell->on_reply = 0;
			} else {
				new_cell->uas.end_request=
					((char*)new_cell->uas.request)+sip_msg_len;
			}
			/* no parallel support in UAC transactions */
			new_cell->on_branch = 0;
			free_sip_msg(req);
		}
	}

	/* for DNS based failover, copy the DNS proxy into transaction */
	if (!disable_dns_failover) {
		new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/);
		if (new_cell->uac[0].proxy==NULL)
			LM_ERR("failed to store DNS info -> no DNS based failover\n");
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer.s = buf;
	request->buffer.len = buf_len;
	new_cell->nr_of_outgoings++;

	if(last_localT) {
		*last_localT = new_cell;
		REF_UNSAFE(new_cell);
	}

	if (SEND_BUFFER(request) == -1) {
		LM_ERR("attempt to send to '%.*s' failed\n",
			dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	}

	if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) {
		t_release_transaction(new_cell);
	} else {
		start_retr(request);
	}

	free_proxy( proxy );
	pkg_free( proxy );

	return 1;

error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);
error2:
	free_proxy( proxy );
	pkg_free( proxy );
error3:
	return ret;
}
Beispiel #14
0
int pv_get_tm_branch_avp(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *val)
{
	int avp_name;
	int_str avp_value;
	unsigned short name_type;
	int idx, idxf, res=0;
	struct usr_avp **old_list=NULL;
	struct usr_avp **avp_list=NULL;
	struct usr_avp *avp;
	int_str avp_value0;
	struct usr_avp *avp0;
	int n=0;
	char *p;

	if (!msg || !val)
		goto error;

	avp_list = get_bavp_list();
	if (!avp_list) {
		pv_get_null(msg, param, val);
		goto success;
	}

	if (!param) {
		LM_ERR("bad parameters\n");
		goto error;
	}

	if (pv_get_avp_name(msg, param, &avp_name, &name_type)) {
		LM_ALERT("BUG in getting bavp name\n");
		goto error;
	}

	/* get the index */
	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
		LM_ERR("invalid index\n");
		goto error;
	}

	/* setting the avp head */
	old_list = set_avp_list(avp_list);
	if (!old_list) {
		LM_CRIT("no bavp head list found\n");
		goto error;
	}

	if ((avp=search_first_avp(name_type, avp_name, &avp_value, 0))==0) {
		pv_get_null(msg, param, val);
		goto success;
	}
	val->flags = PV_VAL_STR;
	if ( (idxf==0 || idxf==PV_IDX_INT) && idx==0) {
		if(avp->flags & AVP_VAL_STR) {
			val->rs = avp_value.s;
		} else {
			val->rs.s = sint2str(avp_value.n, &val->rs.len);
			val->ri = avp_value.n;
			val->flags |= PV_VAL_INT|PV_TYPE_INT;
		}
		goto success;
	}
	if(idxf==PV_IDX_ALL) {
		p = pv_local_buf;
		do {
			if(avp->flags & AVP_VAL_STR) {
				val->rs = avp_value.s;
			} else {
				val->rs.s = sint2str(avp_value.n, &val->rs.len);
			}

			if(p-pv_local_buf+val->rs.len+1>PV_LOCAL_BUF_SIZE) {
				LM_ERR("local buffer length exceeded!\n");
				pv_get_null(msg, param, val);
				goto success;
			}
			memcpy(p, val->rs.s, val->rs.len);
			p += val->rs.len;
			if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE) {
				LM_ERR("local buffer length exceeded\n");
				pv_get_null(msg, param, val);
				goto success;
			}
			memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
			p += PV_FIELD_DELIM_LEN;
		} while ((avp=search_first_avp(name_type, avp_name,
						&avp_value, avp))!=0);
		*p = 0;
		val->rs.s = pv_local_buf;
		val->rs.len = p - pv_local_buf;
		goto success;
	}

	/* we have a numeric index */
	if(idx<0) {
		n = 1;
		avp0 = avp;
		while ((avp0=search_first_avp(name_type, avp_name,
						&avp_value0, avp0))!=0) n++;
		idx = -idx;
		if(idx>n) {
			LM_DBG("index out of range\n");
			pv_get_null(msg, param, val);
			goto success;
		}
		idx = n - idx;
		if(idx==0) {
			if(avp->flags & AVP_VAL_STR) {
				val->rs = avp_value.s;
			} else {
				val->rs.s = sint2str(avp_value.n, &val->rs.len);
				val->ri = avp_value.n;
				val->flags |= PV_VAL_INT|PV_TYPE_INT;
			}
			goto success;
		}
	}
	n=0;
	while(n<idx &&
			(avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0)
		n++;

	if(avp!=0) {
		if(avp->flags & AVP_VAL_STR) {
			val->rs = avp_value.s;
		} else {
			val->rs.s = sint2str(avp_value.n, &val->rs.len);
			val->ri = avp_value.n;
			val->flags |= PV_VAL_INT|PV_TYPE_INT;
		}
	}

	goto success;

error:
	res = -1;
success:
	if (old_list)
		set_avp_list(old_list);
	return res;
}
Beispiel #15
0
int pv_set_tm_branch_avp(struct sip_msg *msg, pv_param_t *param, int op,
		pv_value_t *val)
{
	int avp_name;
	int_str avp_val;
	int flags, res=0;
	unsigned short name_type;
	int idx, idxf;
	struct usr_avp **old_list=NULL;
	struct usr_avp **avp_list=NULL;

	if (!msg || !val)
		goto error;

	avp_list = get_bavp_list();
	if (!avp_list) {
		pv_get_null(msg, param, val);
		goto success;
	}

	if (!param) {
		LM_ERR("bad parameters\n");
		goto error;
	}

	if (pv_get_avp_name(msg, param, &avp_name, &name_type)) {
		LM_ALERT("BUG in getting bavp name\n");
		goto error;
	}

	/* get the index */
	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
		LM_ERR("invalid index\n");
		goto error;
	}

	/* setting the avp head */
	old_list = set_avp_list(avp_list);
	if (!old_list) {
		LM_CRIT("no bavp head list found\n");
		goto error;
	}

	if(val == NULL) {
		if(op == COLONEQ_T || idxf == PV_IDX_ALL)
			destroy_avps(name_type, avp_name, 1);
		else {
			if(idx < 0) {
				LM_ERR("index with negative value\n");
				goto error;
			}
			destroy_index_avp(name_type, avp_name, idx);
		}
		/* restoring head */
		goto success;
	}

	if(op == COLONEQ_T || idxf == PV_IDX_ALL)
		destroy_avps(name_type, avp_name, 1);

	flags = name_type;
	if(val->flags&PV_TYPE_INT) {
		avp_val.n = val->ri;
	} else {
		avp_val.s = val->rs;
		flags |= AVP_VAL_STR;
	}

	if(idxf == PV_IDX_INT || idxf == PV_IDX_PVAR) {
		if(replace_avp(flags, avp_name, avp_val, idx)< 0) {
			LM_ERR("failed to replace bavp\n");
			goto error;
		}
	} else {
		if (add_avp(flags, avp_name, avp_val)<0) {
			LM_ERR("error - cannot add bavp\n");
			goto error;
		}
	}
	goto success;

error:
	res = -1;
success:
	if (old_list)
		set_avp_list(old_list);
	return res;
}
Beispiel #16
0
inline static int w_t_new_request(struct sip_msg* msg, char *p_method,
			char *p_ruri, char *p_from, char *p_to, char *p_body, char *p_ctx)
{
#define CONTENT_TYPE_HDR      "Content-Type: "
#define CONTENT_TYPE_HDR_LEN  (sizeof(CONTENT_TYPE_HDR)-1)
	static dlg_t dlg;
	struct usr_avp **avp_list;
	str ruri;
	str method;
	str body;
	str headers;
	str s;
	int_str ctx;
	char *p;

	memset( &dlg, 0, sizeof(dlg_t));

	/* evaluate the parameters */

	/* method */
	if ( fixup_get_svalue(msg, (gparam_p)p_method, &method)<0 ) {
		LM_ERR("failed to extract METHOD param\n");
		return -1;
	}
	LM_DBG("setting METHOD to <%.*s>\n", method.len, method.s);

	/* ruri - next hop is the same as RURI */
	dlg.hooks.next_hop = dlg.hooks.request_uri = &ruri;
	if ( fixup_get_svalue(msg, (gparam_p)p_ruri, &ruri)<0 ) {
		LM_ERR("failed to extract RURI param\n");
		return -1;
	}
	LM_DBG("setting RURI to <%.*s>\n",
		dlg.hooks.next_hop->len, dlg.hooks.next_hop->s);

	/* FROM URI + display */
	if ( fixup_get_svalue(msg, (gparam_p)p_from, &s)<0 ) {
		LM_ERR("failed to extract FROM param\n");
		return -1;
	}
	if ( (p=q_memrchr(s.s, ' ', s.len))==NULL ) {
		/* no display, only FROM URI */
		dlg.loc_uri = s;
		dlg.loc_dname.s = NULL;
		dlg.loc_dname.len = 0;
	} else {
		/* display + URI */
		dlg.loc_uri.s = p+1;
		dlg.loc_uri.len = s.s+s.len - dlg.loc_uri.s;
		dlg.loc_dname.s = s.s;
		dlg.loc_dname.len = p - s.s;
	}
	LM_DBG("setting FROM to <%.*s> + <%.*s>\n",
		dlg.loc_dname.len, dlg.loc_dname.s,
		dlg.loc_uri.len, dlg.loc_uri.s);

	/* TO URI + display */
	if ( fixup_get_svalue(msg, (gparam_p)p_to, &s)<0 ) {
		LM_ERR("failed to extract TO param\n");
		return -1;
	}
	if ( (p=q_memrchr(s.s, ' ', s.len))==NULL ) {
		/* no display, only TO URI */
		dlg.rem_uri = s;
		dlg.rem_dname.s = NULL;
		dlg.rem_dname.len = 0;
	} else {
		/* display + URI */
		dlg.rem_uri.s = p+1;
		dlg.rem_uri.len = s.s+s.len - dlg.rem_uri.s;
		dlg.rem_dname.s = s.s;
		dlg.rem_dname.len = p - s.s;
	}
	LM_DBG("setting TO to <%.*s> + <%.*s>\n",
		dlg.rem_dname.len, dlg.rem_dname.s,
		dlg.rem_uri.len, dlg.rem_uri.s);

	/* BODY and Content-Type */
	if (p_body!=NULL) {
		if ( fixup_get_svalue(msg, (gparam_p)p_body, &body)<0 ) {
			LM_ERR("failed to extract BODY param\n");
			return -1;
		}
		if ( (p=q_memchr(body.s, ' ', body.len))==NULL ) {
			LM_ERR("Content Type not found in the beginning of body <%.*s>\n",
				body.len, body.s);
			return -1;
		}
		/* build the Content-type header */
		headers.len = CONTENT_TYPE_HDR_LEN + (p-body.s) + CRLF_LEN;
		if ( (headers.s=(char*)pkg_malloc(headers.len))==NULL ) {
			LM_ERR("failed to get pkg mem (needed %d)\n",headers.len);
			return -1;
		}
		memcpy( headers.s, CONTENT_TYPE_HDR, CONTENT_TYPE_HDR_LEN);
		memcpy( headers.s+CONTENT_TYPE_HDR_LEN, body.s, p-body.s);
		memcpy( headers.s+CONTENT_TYPE_HDR_LEN+(p-body.s), CRLF, CRLF_LEN);
		/* set the body */
		body.len = body.s + body.len - (p+1);
		body.s = p + 1;
		LM_DBG("setting BODY to <%.*s> <%.*s>\n",
			headers.len, headers.s,
			body.len, body.s );
	} else {
		body.s = NULL;
		body.len = 0;
		headers.s = NULL;
		headers.len = 0;
	}

	/* context value */
	if (p_ctx!=NULL) {
		if ( fixup_get_svalue(msg, (gparam_p)p_ctx, &ctx.s)<0 ) {
			LM_ERR("failed to extract BODY param\n");
			if (p_body) pkg_free(headers.s);
			return -1;
		}
		LM_DBG("setting CTX AVP to <%.*s>\n", ctx.s.len, ctx.s.s);
		avp_list = set_avp_list( &dlg.avps );
		if (!add_avp( AVP_VAL_STR, uac_ctx_avp_id, ctx))
			LM_ERR("failed to add ctx AVP, ignorring...\n");
		set_avp_list( avp_list );
	}

	/* add cseq */
	dlg.loc_seq.value = DEFAULT_CSEQ;
	dlg.loc_seq.is_set = 1;

	/* add callid */
	generate_callid(&dlg.id.call_id);

	/* add FROM tag */
	generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id);
	/* TO tag is empty as this is a initial request */
	dlg.id.rem_tag.s = NULL;
	dlg.id.rem_tag.len = 0;

	/* do the actual sending now */
	if ( t_uac( &method, headers.s?&headers:NULL, body.s?&body:NULL,
	&dlg, 0, 0, 0) <= 0 ) {
		LM_ERR("failed to send the request out\n");
		if (headers.s) pkg_free(headers.s);
		if (dlg.avps) destroy_avp_list(&dlg.avps);
		return -1;
	}

	/* success -> do cleanup */
	if (headers.s) pkg_free(headers.s);
	return 1;
}
Beispiel #17
0
void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elapsed_msecs) {
    struct cell *t = 0;
    int rc = -1, experimental_rc = -1;
    int result = CSCF_RETURN_TRUE;
    saved_transaction_t* data = 0;
    struct sip_msg* req;

    str xml_data = {0, 0}, ccf1 = {0, 0}, ccf2 = {0, 0}, ecf1 = {0, 0}, ecf2 = {0, 0};
    ims_subscription* s = 0;
    rerrno = R_FINE;

    if (!param) {
        LM_DBG("No transaction data this must have been called from usrloc cb impu deleted - just log result code and then exit");
        cxdx_get_result_code(saa, &rc);
        cxdx_get_experimental_result_code(saa, &experimental_rc);

        if (saa) cdpb.AAAFreeMessage(&saa);

        if (!rc && !experimental_rc) {
            LM_ERR("bad SAA result code\n");
            return;
        }
        switch (rc) {
            case -1:
                LM_DBG("Received Diameter error\n");
                return;

            case AAA_UNABLE_TO_COMPLY:
                LM_DBG("Unable to comply\n");
                return;

            case AAA_SUCCESS:
                LM_DBG("received AAA success\n");
                return;

            default:
                LM_ERR("Unknown error\n");
                return;
        }

    } else {
        LM_DBG("There is transaction data this must have been called from save or assign server unreg");
        data = (saved_transaction_t*) param;
        if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
            LM_ERR("t_continue: transaction not found and t is now pointing to %p and will be set to NULL\n", t);
            t = NULL;
            rerrno = R_SAR_FAILED;
            goto error_no_send;
        }

	set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
	set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
	set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
	set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
	set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
	set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

        get_act_time();

        req = get_request_from_tx(t);
        if (!req) {
            LM_ERR("Failed to get SIP Request from Transaction\n");
            goto error_no_send;
        }
        
        if (is_timeout) {
        	update_stat(stat_sar_timeouts, 1);
            LM_ERR("Transaction timeout - did not get SAA\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }
        if (!saa) {
            LM_ERR("Error sending message via CDP\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }

        update_stat(sar_replies_received, 1);
        update_stat(sar_replies_response_time, elapsed_msecs);

        
        /* check and see that all the required headers are available and can be parsed */
        if (parse_message_for_register(req) < 0) {
            LM_ERR("Unable to parse register message correctly\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }

        cxdx_get_result_code(saa, &rc);
        cxdx_get_experimental_result_code(saa, &experimental_rc);
        cxdx_get_charging_info(saa, &ccf1, &ccf2, &ecf1, &ecf2);

        if (!rc && !experimental_rc) {
            LM_ERR("bad SAA result code\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }

        switch (rc) {
            case -1:
                LM_DBG("Received Diameter error\n");
                rerrno = R_SAR_FAILED;
                goto error;

            case AAA_UNABLE_TO_COMPLY:
                LM_DBG("Unable to comply\n");
                rerrno = R_SAR_FAILED;
                goto error;

            case AAA_SUCCESS:
                LM_DBG("received AAA success for SAR - SAA\n");
                break;

            default:
                LM_ERR("Unknown error\n");
                rerrno = R_SAR_FAILED;
                goto error;
        }
        //success
        //if this is from a save (not a server assign unreg) and expires is zero we don't update usrloc as this is a dereg and usrloc was updated previously
        if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER && data->expires == 0) {
            LM_DBG("no need to update usrloc - already done for de-reg\n");
            result = CSCF_RETURN_TRUE;
            goto success;
        }

        xml_data = cxdx_get_user_data(saa);
        /*If there is XML user data we must be able to parse it*/
        if (xml_data.s && xml_data.len > 0) {
            LM_DBG("Parsing user data string from SAA\n");
            s = parse_user_data(xml_data);
            if (!s) {
                LM_ERR("Unable to parse user data XML string\n");
                rerrno = R_SAR_FAILED;
                goto error;
            }
            LM_DBG("Successfully parse user data XML setting ref to 1 (we are referencing it)\n");
            s->ref_count = 1; //no need to lock as nobody else will be referencing this piece of memory just yet
        } else {
            if (data->require_user_data) {
                LM_ERR("We require User data for this assignment/register and none was supplied\n");
                rerrno = R_SAR_FAILED;
                result = CSCF_RETURN_FALSE;
                goto done;
            }
        }

        if (data->sar_assignment_type == AVP_IMS_SAR_REGISTRATION || data->sar_assignment_type == AVP_IMS_SAR_RE_REGISTRATION) {
            if (s) {
                if (build_p_associated_uri(s) != 0) {
                    LM_ERR("Unable to build p_associated_uri\n");
                    rerrno = R_SAR_FAILED;
                    goto error;
                }
            }

        }

        if (s) {
            //here we update the contacts and also build the new contact header for the 200 OK reply
            if (update_contacts(req, data->domain, &data->public_identity, data->sar_assignment_type, &s, &ccf1, &ccf2, &ecf1, &ecf2, &data->contact_header) <= 0) {
                LM_ERR("Error processing REGISTER\n");
                rerrno = R_SAR_FAILED;
                goto error;
            }
        }
        
        if (data->contact_header) {
            LM_DBG("Updated contacts: %.*s\n", data->contact_header->data_len, data->contact_header->buf);
        } else {
            LM_DBG("Updated unreg contact\n");
        }
        
    }

success:
    update_stat(accepted_registrations, 1);

done:
    if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER)
        reg_send_reply_transactional(req, data->contact_header, t);
    LM_DBG("DBG:SAR Async CDP callback: ... Done resuming transaction\n");

    create_return_code(result);

    //release our reference on subscription (s)
    if (s) 
        ul.unref_subscription(s);
    
    //free memory
    if (saa) cdpb.AAAFreeMessage(&saa);
    if (t) {
//        del_nonshm_lump_rpl(&req->reply_lump);
        tmb.unref_cell(t);
    }
    //free path vector pkg memory
//    reset_path_vector(req);

    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_data(data);
    return;

error:
    create_return_code(-2);
    if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER)
        reg_send_reply_transactional(req, data->contact_header, t);
		
error_no_send: //if we don't have the transaction then we can't send a transaction response
    update_stat(rejected_registrations, 1);
    //free memory
    if (saa) cdpb.AAAFreeMessage(&saa);
    if (t) {
//        del_nonshm_lump_rpl(&req->reply_lump);
        tmb.unref_cell(t);
    }
    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_data(data);
    return;
}
Beispiel #18
0
void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
{
	static struct tmcb_params params = {0,0,0,0};
	struct tm_callback    *cbp;
	avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to, *backup_uri_from, *backup_uri_to;

	params.req = req;
	params.code = code;

	if (req_in_tmcb_hl->first==0)
		return;

	backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, &trans->uri_avps_from );
	backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, &trans->uri_avps_to );
	backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, &trans->user_avps_from );
	backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, &trans->user_avps_to );
	backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, &trans->domain_avps_from);
	backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, &trans->domain_avps_to);
	for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next)  {
		DBG("DBG: trans=%p, callback type %d, id %d entered\n",
			trans, cbp->types, cbp->id );
		params.param = &(cbp->param);
		cbp->callback( trans, cbp->types, &params );
	}
	set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, backup_uri_to );
	set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, backup_uri_from );
	set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, backup_dom_to );
	set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, backup_dom_from );
	set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, backup_to );
	set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, backup_from );
}
Beispiel #19
0
void async_cdp_callback(int is_timeout, void *param, AAAMessage *maa, long elapsed_msecs) {
    int i, j;
    int rc = -1, experimental_rc = -1;
    saved_transaction_t* data = (saved_transaction_t*) param;
    struct cell *t = 0;
    int result = CSCF_RETURN_TRUE;
    int sip_number_auth_items;
    struct auth_data_item_list *adi_list = 0;
    AAA_AVP *auth_data;
    auth_data = 0;
    int item_number;
    str authenticate = {0, 0}, authorization2 = {0, 0}, ck = {0, 0}, ik = {0, 0}, ip = {0, 0}, ha1 = {0, 0};
    str line_identifier = {0, 0};
    str response_auth = {0, 0}, digest_realm = {0, 0};
    auth_vector *av = 0, **avlist = 0;
    HASHHEX ha1_hex;
    HASHHEX result_hex;
    str etsi_nonce = {0, 0};
    str private_identity, public_identity;
    str algorithm;

    if (is_timeout) {
    	update_stat(stat_mar_timeouts, 1);
        LM_ERR("Transaction timeout - did not get MAA\n");
        result = CSCF_RETURN_ERROR;
        goto error;
    }
    if (!maa) {
        LM_ERR("Error sending message via CDP\n");
        result = CSCF_RETURN_ERROR;
        goto error;
    }

    update_stat(mar_replies_received, 1);
    update_stat(mar_replies_response_time, elapsed_msecs);

    if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
        LM_ERR("t_continue: transaction not found\n");
        result = CSCF_RETURN_ERROR;
        goto error;
    }

    /* get the private_identity */
    private_identity = get_private_identity(t->uas.request, data->realm, data->is_proxy_auth);
    if (!private_identity.len) {
        LM_ERR("No private identity specified (Authorization: username)\n");
        stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_PRIVATE);
        result = CSCF_RETURN_FALSE;
        goto error;
    }
    /* get the public_identity */
    public_identity = get_public_identity(t->uas.request);
    if (!public_identity.len) {
        LM_ERR("No public identity specified (To:)\n");
        stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_PUBLIC);
        result = CSCF_RETURN_FALSE;
        goto error;
    }

    //get each individual element from the MAA
    cxdx_get_result_code(maa, &rc);
    cxdx_get_experimental_result_code(maa, &experimental_rc);
    cxdx_get_sip_number_auth_items(maa, &sip_number_auth_items);

    //now assign the auth_data_item elements
    //there can be many of these in the MAA
    struct auth_data_item *adi;
    int adi_len;
    char *p;
    while ((cxdx_get_auth_data_item_answer(maa, &auth_data, &item_number,
            &algorithm, &authenticate, &authorization2,
            &ck, &ik,
            &ip,
            &ha1, &response_auth, &digest_realm,
            &line_identifier))) {

        //create an auth_data_item for each entry in the MAA
        adi_len = sizeof (struct auth_data_item) +authenticate.len + authorization2.len + ck.len + ik.len + ip.len + ha1.len + line_identifier.len + response_auth.len + digest_realm.len + algorithm.len;
        adi = (struct auth_data_item*) shm_malloc(adi_len);
        if (!adi) {
            LM_CRIT("Out of memory!\n");
            result = CSCF_RETURN_ERROR;
            goto done;
        }

        memset(adi, 0, adi_len);

        //put all elements in the auth_data_item entry
        p = (char*) (adi + 1);

        adi->authenticate.s = p;
        adi->authenticate.len = authenticate.len;
        memcpy(p, authenticate.s, authenticate.len);
        p += authenticate.len;

        adi->authorization.s = p;
        adi->authorization.len = authorization2.len;
        memcpy(p, authorization2.s, authorization2.len);
        p += authorization2.len;

        adi->auth_scheme.s = p;
        adi->auth_scheme.len = algorithm.len;
        memcpy(p, algorithm.s, algorithm.len);
        p += algorithm.len;

        adi->ck.s = p;
        adi->ck.len = ck.len;
        memcpy(p, ck.s, ck.len);
        p += ck.len;

        adi->ik.s = p;
        adi->ik.len = ik.len;
        memcpy(p, ik.s, ik.len);
        p += ik.len;

        adi->ip.s = p;
        adi->ip.len = ip.len;
        memcpy(p, ip.s, ip.len);
        p += ip.len;

        adi->ha1.s = p;
        adi->ha1.len = ha1.len;
        memcpy(p, ha1.s, ha1.len);
        p += ha1.len;

        adi->line_identifier.s = p;
        adi->line_identifier.len = line_identifier.len;
        memcpy(p, line_identifier.s, line_identifier.len);
        p += line_identifier.len;

        adi->response_auth.s = p;
        adi->response_auth.len = response_auth.len;
        memcpy(p, response_auth.s, response_auth.len);
        p += response_auth.len;

        adi->digest_realm.s = p;
        adi->digest_realm.len = digest_realm.len;
        memcpy(p, digest_realm.s, digest_realm.len);
        p += digest_realm.len;

        if (p != (((char*) adi) + adi_len)) {
            LM_CRIT("buffer overflow\n");
            shm_free(adi);
            adi = 0;
            result = CSCF_RETURN_ERROR;
            goto done;
        }
        auth_data->code = -auth_data->code;
        adi->item_number = item_number;

        int len = sizeof (struct auth_data_item_list);
        adi_list = (struct auth_data_item_list*) shm_malloc(len);
        memset(adi_list, 0, len);

        if (adi_list->first == 0) {
            adi_list->first = adi_list->last = adi;
        } else {
            adi_list->last->next = adi;
            adi->previous = adi_list->last;
            adi_list->last = adi;
        }
    }

    if (!(rc) && !(experimental_rc)) {
        stateful_request_reply_async(t, t->uas.request, 480, MSG_480_DIAMETER_MISSING_AVP);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    switch (rc) {
        case -1:
            switch (experimental_rc) {
                case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN:
                    stateful_request_reply_async(t, t->uas.request, 403, MSG_403_USER_UNKNOWN);
                    result = CSCF_RETURN_FALSE;
                    break;
                case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH:
                    stateful_request_reply_async(t, t->uas.request, 403, MSG_403_IDENTITIES_DONT_MATCH);
                    result = CSCF_RETURN_FALSE;
                    break;
                case RC_IMS_DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED:
                    stateful_request_reply_async(t, t->uas.request, 403, MSG_403_AUTH_SCHEME_UNSOPPORTED);
                    result = CSCF_RETURN_FALSE;
                    break;

                default:
                    stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNKOWN_EXPERIMENTAL_RC);
                    result = CSCF_RETURN_FALSE;
            }
            break;

        case AAA_UNABLE_TO_COMPLY:
            stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNABLE_TO_COMPLY);
            result = CSCF_RETURN_FALSE;
            break;

        case AAA_SUCCESS:
            goto success;
            break;

        default:
            stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNKOWN_RC);
            result = CSCF_RETURN_FALSE;
    }

    goto done;

success:

    if (!sip_number_auth_items) {
        stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_AUTH_DATA);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    avlist = shm_malloc(sizeof (auth_vector *) * sip_number_auth_items);
    if (!avlist) {
        stateful_request_reply_async(t, t->uas.request, 403, MSG_480_HSS_ERROR);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    sip_number_auth_items = 0;

    struct auth_data_item *tmp;
    tmp = adi_list->first;

    while (tmp) {

        if (tmp->ip.len)
            av = new_auth_vector(tmp->item_number, tmp->auth_scheme, empty_s,
                tmp->ip, empty_s, empty_s);
        else if (tmp->line_identifier.len)
            av = new_auth_vector(tmp->item_number, tmp->auth_scheme, empty_s,
                line_identifier, empty_s, empty_s);
        else if (tmp->ha1.len) {
            if (tmp->response_auth.len) //HSS check
            {
                memset(ha1_hex, 0, HASHHEXLEN + 1);
                memcpy(ha1_hex, tmp->ha1.s,
                        tmp->ha1.len > HASHHEXLEN ? 32 : tmp->ha1.len);

                etsi_nonce.len = tmp->authenticate.len / 2;
                etsi_nonce.s = pkg_malloc(etsi_nonce.len);
                if (!etsi_nonce.s) {
                    LM_ERR("error allocating %d bytes\n", etsi_nonce.len);
                    goto done;
                }
                etsi_nonce.len = base16_to_bin(tmp->authenticate.s,
                        tmp->authenticate.len, etsi_nonce.s);

                calc_response(ha1_hex, &etsi_nonce, &empty_s, &empty_s,
                        &empty_s, 0, &(t->uas.request->first_line.u.request.method),
                        &scscf_name_str, 0, result_hex);
                pkg_free(etsi_nonce.s);

                if (!tmp->response_auth.len == 32
                        || strncasecmp(tmp->response_auth.s, result_hex, 32)) {
                    LM_ERR("The HSS' Response-Auth is different from what we compute locally!\n"
                            " BUT! If you sent an MAR with auth scheme unknown (HSS-Selected Authentication), this is normal.\n"
                            "HA1=\t|%s|\nNonce=\t|%.*s|\nMethod=\t|%.*s|\nuri=\t|%.*s|\nxresHSS=\t|%.*s|\nxresSCSCF=\t|%s|\n",
                            ha1_hex,
                            tmp->authenticate.len, tmp->authenticate.s,
                            t->uas.request->first_line.u.request.method.len, t->uas.request->first_line.u.request.method.s,
                            scscf_name_str.len, scscf_name_str.s,
                            tmp->response_auth.len, tmp->response_auth.s,
                            result_hex);
                    //stateful_register_reply(msg,514,MSG_514_HSS_AUTH_FAILURE);
                    //goto done;
                }
            }
            av = new_auth_vector(tmp->item_number, tmp->auth_scheme,
                    tmp->authenticate, tmp->ha1, empty_s, empty_s);
        } else
            av = new_auth_vector(tmp->item_number, tmp->auth_scheme,
                tmp->authenticate, tmp->authorization, tmp->ck, tmp->ik);

        if (sip_number_auth_items == 0)
            avlist[sip_number_auth_items++] = av;
        else {
            i = sip_number_auth_items;
            while (i > 0 && avlist[i - 1]->item_number > av->item_number)
                i--;
            for (j = sip_number_auth_items; j > i; j--)
                avlist[j] = avlist[j - 1];
            avlist[i] = av;
            sip_number_auth_items++;
        }

        //TODO need to confirm that removing this has done no problems
        //tmp->auth_data->code = -tmp->auth_data->code;

	LM_DBG("Added new auth-vector.\n");

        tmp = tmp->next;
    }

    //MAA returns a whole list of av! Which should we use?
    //right now we take the first and put the rest in the AV queue
    //then we use the first one and then add it to the queue as sent!

    for (i = 1; i < sip_number_auth_items; i++)
        if (!add_auth_vector(private_identity, public_identity, avlist[i]))
            free_auth_vector(avlist[i]);

    if (!pack_challenge(t->uas.request, data->realm, avlist[0], data->is_proxy_auth)) {
        stateful_request_reply_async(t, t->uas.request, 500, MSG_500_PACK_AV);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    if (data->is_proxy_auth)
        stateful_request_reply_async(t, t->uas.request, 407, MSG_407_CHALLENGE);
    else
        stateful_request_reply_async(t, t->uas.request, 401, MSG_401_CHALLENGE);

done:
    if (avlist) {
        start_reg_await_timer(avlist[0]); //start the timer to remove stale or unused Auth Vectors

        //now we add it to the queue as sent as we have already sent the challenge and used it and set the status to SENT
        if (!add_auth_vector(private_identity, public_identity, avlist[0]))
            free_auth_vector(avlist[0]);
    }

    //free memory
    if (maa) cdpb.AAAFreeMessage(&maa);
    if (avlist) {
        shm_free(avlist);
        avlist = 0;
    }

    if (adi_list) {
        struct auth_data_item *tmp1 = adi_list->first;
        while (tmp1) {
            struct auth_data_item *tmp2 = tmp1->next;
            shm_free(tmp1);
            tmp1 = tmp2;
        }
        shm_free(adi_list);
        adi_list = 0;
    }

    LM_DBG("DBG:UAR Async CDP callback: ... Done resuming transaction\n");
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    //make sure we delete any private lumps we created
    create_return_code(result);
    if (t) {
        del_nonshm_lump_rpl(&t->uas.request->reply_lump);
        tmb.unref_cell(t);
    }
    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_data(data);
    return;

error:
    //don't need to set result code as by default it is ERROR!

    if (t) {
        del_nonshm_lump_rpl(&t->uas.request->reply_lump);
        tmb.unref_cell(t);
    }
    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_data(data);
}
struct cell*  build_cell( struct sip_msg* p_msg )
{
	struct cell* new_cell;
	int          sip_msg_len;
	avp_list_t* old;

	/* allocs a new cell */
	new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) );
	if  ( !new_cell ) {
		ser_error=E_OUT_OF_MEM;
		return NULL;
	}

	/* filling with 0 */
	memset( new_cell, 0, sizeof( struct cell ) );

	/* UAS */
	new_cell->uas.response.my_T=new_cell;
	init_rb_timers(&new_cell->uas.response);
	/* timers */
	init_cell_timers(new_cell);

	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI,  &new_cell->uri_avps_from );
	new_cell->uri_avps_from = *old;
	*old = 0;

	old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI,  &new_cell->uri_avps_to );
	new_cell->uri_avps_to = *old;
	*old = 0;

	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER,  &new_cell->user_avps_from );
	new_cell->user_avps_from = *old;
	*old = 0;

	old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER,  &new_cell->user_avps_to );
	new_cell->user_avps_to = *old;
	*old = 0;

	     /* We can just store pointer to domain avps in the transaction context,
	      * because they are read-only
	      */
	new_cell->domain_avps_from = get_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN);
	new_cell->domain_avps_to = get_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN);

	/* enter callback, which may potentially want to parse some stuff,
	 * before the request is shmem-ized */
	if ( p_msg && has_reqin_tmcbs() )
		run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);

	if (p_msg) {
		/* clean possible previous added vias/clen header or else they would 
		 * get propagated in the failure routes */
		free_via_clen_lump(&p_msg->add_rm);
		new_cell->uas.request = sip_msg_cloner(p_msg,&sip_msg_len);
		if (!new_cell->uas.request)
			goto error;
		new_cell->uas.end_request=((char*)new_cell->uas.request)+sip_msg_len;
	}

	/* UAC */
	init_branches(new_cell);

	new_cell->relayed_reply_branch   = -1;
	/* new_cell->T_canceled = T_UNDEFINED; */

	init_synonym_id(new_cell);
	init_cell_lock(  new_cell );
	return new_cell;

error:
	destroy_avp_list(&new_cell->user_avps_from);
	destroy_avp_list(&new_cell->user_avps_to);
	destroy_avp_list(&new_cell->uri_avps_from);
	destroy_avp_list(&new_cell->uri_avps_to);
	shm_free(new_cell);
	/* unlink transaction AVP list and link back the global AVP list (bogdan)*/
	reset_avps();
	return NULL;
}
Beispiel #21
0
static inline int pre_print_uac_request( struct cell *t, int branch,
					struct sip_msg *request, struct sip_msg_body **body_clone)
{
	int backup_route_type;
	struct usr_avp **backup_list;
	char *p;

	/* ... we calculate branch ... */
	if (!t_calc_branch(t, branch, request->add_to_branch_s,
			&request->add_to_branch_len ))
	{
		LM_ERR("branch computation failed\n");
		goto error;
	}

	/* from now on, flag all new lumps with LUMPFLAG_BRANCH flag in order to
	 * be able to remove them later --bogdan */
	set_init_lump_flags(LUMPFLAG_BRANCH);

	/* copy path vector into branch */
	if (request->path_vec.len) {
		t->uac[branch].path_vec.s =
			shm_realloc(t->uac[branch].path_vec.s, request->path_vec.len+1);
		if (t->uac[branch].path_vec.s==NULL) {
			LM_ERR("shm_realloc failed\n");
			goto error;
		}
		t->uac[branch].path_vec.len = request->path_vec.len;
		memcpy( t->uac[branch].path_vec.s, request->path_vec.s,
			request->path_vec.len+1);
	}

	/* do the same for the advertised port & address */
	if (request->set_global_address.len) {
		t->uac[branch].adv_address.s = shm_realloc(t->uac[branch].adv_address.s,
			request->set_global_address.len+1);
		if (t->uac[branch].adv_address.s==NULL) {
			LM_ERR("shm_realloc failed for storing the advertised address "
				"(len=%d)\n",request->set_global_address.len);
			goto error;
		}
		t->uac[branch].adv_address.len = request->set_global_address.len;
		memcpy( t->uac[branch].adv_address.s, request->set_global_address.s,
			request->set_global_address.len+1);
	}
	if (request->set_global_port.len) {
		t->uac[branch].adv_port.s = shm_realloc(t->uac[branch].adv_port.s,
			request->set_global_port.len+1);
		if (t->uac[branch].adv_port.s==NULL) {
			LM_ERR("shm_realloc failed for storing the advertised port "
				"(len=%d)\n",request->set_global_port.len);
			goto error;
		}
		t->uac[branch].adv_port.len = request->set_global_port.len;
		memcpy( t->uac[branch].adv_port.s, request->set_global_port.s,
			request->set_global_port.len+1);
	}


	/********** run route & callback ************/

	/* run branch route, if any; run it before RURI's DNS lookup
	 * to allow to be changed --bogdan */
	if (t->on_branch) {
		/* need to pkg_malloc the dst_uri */
		if ( request->dst_uri.s && request->dst_uri.len>0 ) {
			if ( (p=pkg_malloc(request->dst_uri.len))==0 ) {
				LM_ERR("no more pkg mem\n");
				ser_error=E_OUT_OF_MEM;
				goto error;
			}
			memcpy( p, request->dst_uri.s, request->dst_uri.len);
			request->dst_uri.s = p;
		}
		/* need to pkg_malloc the new_uri */
		if ( (p=pkg_malloc(request->new_uri.len))==0 ) {
			LM_ERR("no more pkg mem\n");
			ser_error=E_OUT_OF_MEM;
			goto error;
		}
		memcpy( p, request->new_uri.s, request->new_uri.len);
		request->new_uri.s = p;
		request->parsed_uri_ok = 0;
		/* make a clone of the original body, to restore it later */
		if (clone_sip_msg_body( request, NULL, body_clone, 0)!=0) {
			LM_ERR("faile to clone the body, branch route changes will be"
				" preserved\n");
		}
		/* make available the avp list from transaction */
		backup_list = set_avp_list( &t->user_avps );
		/* run branch route */
		swap_route_type( backup_route_type, BRANCH_ROUTE);

		_tm_branch_index = branch;
		if(run_top_route(sroutes->branch[t->on_branch].a,request)&ACT_FL_DROP){
			LM_DBG("dropping branch <%.*s>\n", request->new_uri.len,
					request->new_uri.s);
			_tm_branch_index = 0;
			/* restore the route type */
			set_route_type( backup_route_type );
			/* restore original avp list */
			set_avp_list( backup_list );
			goto error;
		}

		_tm_branch_index = 0;
		/* restore the route type */
		set_route_type( backup_route_type );
		/* restore original avp list */
		set_avp_list( backup_list );
	}

	/* run the specific callbacks for this transaction */
	run_trans_callbacks( TMCB_REQUEST_FWDED, t, request, 0,
			-request->REQ_METHOD);

	/* copy dst_uri into branch (after branch route possible updated it) */
	if (request->dst_uri.len) {
		t->uac[branch].duri.s =
			shm_realloc(t->uac[branch].duri.s, request->dst_uri.len);
		if (t->uac[branch].duri.s==NULL) {
			LM_ERR("shm_realloc failed\n");
			goto error;
		}
		t->uac[branch].duri.len = request->dst_uri.len;
		memcpy( t->uac[branch].duri.s,request->dst_uri.s,request->dst_uri.len);
	}

	return 0;
error:
	return -1;
}
Beispiel #22
0
void handle_ebr_ipc(int sender, void *payload)
{
	ebr_ipc_job *job = (ebr_ipc_job*)payload;
	struct usr_avp **old_avps;
	struct sip_msg req;

	LM_DBG("EBR notification received via IPC for event %.*s\n",
		job->ev->event_name.len, job->ev->event_name.s);

	if (job->flags&EBR_SUBS_TYPE_NOTY) {

		/* this is a job for notifiying on an event */

		/* push our list of AVPs */
		old_avps = set_avp_list( &job->avps );

		/* prepare a fake/dummy request */
		memset( &req, 0, sizeof(struct sip_msg));
		req.first_line.type = SIP_REQUEST;
		req.first_line.u.request.method.s= "DUMMY";
		req.first_line.u.request.method.len= 5;
		req.first_line.u.request.uri.s= "sip:[email protected]";
		req.first_line.u.request.uri.len= 19;
		req.rcv.src_ip.af = AF_INET;
		req.rcv.dst_ip.af = AF_INET;

		LM_DBG("using transaction reference %X:%X\n",
			job->tm.hash, job->tm.label);
		if (ebr_tmb.t_set_remote_t && job->tm.hash!=0 && job->tm.label!=0 )
			ebr_tmb.t_set_remote_t( &job->tm );

		/* route the notification route */
		set_route_type( REQUEST_ROUTE );
		run_top_route( rlist[(int)(long)job->data].a, &req);

		if (ebr_tmb.t_set_remote_t)
			ebr_tmb.t_set_remote_t( NULL );

		/* cleanup over route execution */
		set_avp_list( old_avps );
		free_sip_msg( &req );

		/* destroy everything */
		destroy_avp_list( &job->avps );
		shm_free(job);

	} else {

		/* this is a job for resuming on WAIT */

		/* pass the list of AVPs to be pushed into the msg */
		((async_ctx*)job->data)->resume_param = job->avps;

		/* invoke the global resume ASYNC function */
		async_script_resume_f(ASYNC_FD_NONE, job->data /*the async ctx*/ );

		shm_free(job);

	}

	return;
}
Beispiel #23
0
/*  This function is called whenever a reply for our module is received; 
  * we need to register  this function on module initialization;
  *  Returns :   0 - core router stops
  *              1 - core router relay statelessly
  */
int reply_received( struct sip_msg  *p_msg )
{
	int msg_status;
	int last_uac_status;
	int branch;
	int reply_status;
	utime_t timer;
	/* has the transaction completed now and we need to clean-up? */
	branch_bm_t cancel_bitmap;
	struct ua_client *uac;
	struct cell *t;
	struct usr_avp **backup_list;
	unsigned int has_reply_route;

	set_t(T_UNDEFINED);

	/* make sure we know the associated transaction ... */
	if (t_check(p_msg, &branch ) == -1) goto not_found;

	/*... if there is none, tell the core router to fwd statelessly */
	t = get_t();
	if ((t == 0) || (t == T_UNDEFINED)) goto not_found;

	cancel_bitmap=0;
	msg_status=p_msg->REPLY_STATUS;

	uac=&t->uac[branch];
	LM_DBG("org. status uas=%d, uac[%d]=%d local=%d is_invite=%d)\n",
		t->uas.status, branch, uac->last_received, 
		is_local(t), is_invite(t));
	last_uac_status=uac->last_received;
	if_update_stat( tm_enable_stats, tm_rcv_rpls , 1);

	/* it's a cancel which is not e2e ? */
	if ( get_cseq(p_msg)->method_id==METHOD_CANCEL && is_invite(t) ) {
		/* ... then just stop timers */
		reset_timer( &uac->local_cancel.retr_timer);
		if ( msg_status >= 200 ) {
				reset_timer( &uac->local_cancel.fr_timer);
		}
		LM_DBG("reply to local CANCEL processed\n");
		goto done;
	}

	/* *** stop timers *** */
	/* stop retransmission */
	reset_timer(&uac->request.retr_timer);

	/* stop final response timer only if I got a final response */
	if ( msg_status >= 200 ) {
		reset_timer( &uac->request.fr_timer);
	}

	/* acknowledge negative INVITE replies (do it before detailed
	 * on_reply processing, which may take very long, like if it
	 * is attempted to establish a TCP connection to a fail-over dst */
	if (is_invite(t) && ((msg_status >= 300) ||
	(is_local(t) && !no_autoack(t) && msg_status >= 200) )) {
		if (send_ack(p_msg, t, branch)!=0)
			LM_ERR("failed to send ACK (local=%s)\n", is_local(t)?"yes":"no");
	}

	_tm_branch_index = branch;

	/* processing of on_reply block */
	has_reply_route = (t->on_reply) || (t->uac[branch].on_reply);
	if (has_reply_route) {
		if (onreply_avp_mode) {
			/* lock the reply*/
			LOCK_REPLIES( t );
			/* set the as avp_list the one from transaction */
			backup_list = set_avp_list(&t->user_avps);
		} else {
			backup_list = 0;
		}
		/* transfer transaction flag to branch context */
		p_msg->flags = t->uas.request->flags;
		setb0flags(t->uac[branch].br_flags);
		/* run block - first per branch and then global one */
		if ( t->uac[branch].on_reply &&
		(run_top_route(onreply_rlist[t->uac[branch].on_reply].a,p_msg)
		&ACT_FL_DROP) && (msg_status<200) ) {
			if (onreply_avp_mode) {
				UNLOCK_REPLIES( t );
				set_avp_list( backup_list );
			}
			LM_DBG("dropping provisional reply %d\n", msg_status);
			goto done;
		}
		if ( t->on_reply && (run_top_route(onreply_rlist[t->on_reply].a,p_msg)
		&ACT_FL_DROP) && (msg_status<200) ) {
			if (onreply_avp_mode) {
				UNLOCK_REPLIES( t );
				set_avp_list( backup_list );
			}
			LM_DBG("dropping provisional reply %d\n", msg_status);
			goto done;
		}
		/* transfer current message context back to t */
		t->uac[branch].br_flags = getb0flags();
		t->uas.request->flags = p_msg->flags;
		if (onreply_avp_mode)
			/* restore original avp list */
			set_avp_list( backup_list );
	}

	if (!onreply_avp_mode || !has_reply_route)
		/* lock the reply*/
		LOCK_REPLIES( t );

	/* mark that the UAC received replies */
	uac->flags |= T_UAC_HAS_RECV_REPLY;

	/* we fire a cancel on spot if (a) branch is marked "to be canceled" or (b)
	 * the whole transaction was canceled (received cancel) and no cancel sent
	 * yet on this branch; and of course, only if a provisional reply :) */
	if (t->uac[branch].flags&T_UAC_TO_CANCEL_FLAG ||
	((t->flags&T_WAS_CANCELLED_FLAG) && !t->uac[branch].local_cancel.buffer.s)) {
		if ( msg_status < 200 )
			/* reply for an UAC with a pending cancel -> do cancel now */
			cancel_branch(t, branch);
		/* reset flag */
		t->uac[branch].flags &= ~(T_UAC_TO_CANCEL_FLAG);
	}

	if (is_local(t)) {
		reply_status = local_reply(t,p_msg, branch,msg_status,&cancel_bitmap);
		if (reply_status == RPS_COMPLETED) {
			cleanup_uac_timers(t);
			if (is_invite(t)) cancel_uacs(t, cancel_bitmap);
			/* There is no need to call set_final_timer because we know
			 * that the transaction is local */
			put_on_wait(t);
		}
	} else {
		reply_status = relay_reply(t,p_msg,branch,msg_status,&cancel_bitmap);
		/* clean-up the transaction when transaction completed */
		if (reply_status == RPS_COMPLETED) {
			/* no more UAC FR/RETR (if I received a 2xx, there may
			 * be still pending branches ...
			 */
			cleanup_uac_timers(t);
			if (is_invite(t)) cancel_uacs(t, cancel_bitmap);
			/* FR for negative INVITES, WAIT anything else */
			/* set_final_timer(t); */
		}
	}
	
	if (reply_status!=RPS_PROVISIONAL)
		goto done;
	
	/* update FR/RETR timers on provisional replies */
	if (msg_status < 200 && (restart_fr_on_each_reply ||
	((last_uac_status<msg_status) &&
	((msg_status >= 180) || (last_uac_status == 0)))
	) ) { /* provisional now */
		if (is_invite(t)) {
			/* invite: change FR to longer FR_INV, do not
			 * attempt to restart retransmission any more
			 */
			backup_list = set_avp_list(&t->user_avps);
			if (!fr_inv_avp2timer(&timer)) {
				LM_DBG("FR_INV_TIMER = %lld\n", timer);
				set_timer(&uac->request.fr_timer,
					FR_INV_TIMER_LIST, &timer);
			} else {
				set_timer(& uac->request.fr_timer, FR_INV_TIMER_LIST, 0);
			}
			set_avp_list(backup_list);
		} else {
			/* non-invite: restart retransmissions (slow now) */
			uac->request.retr_list = RT_T2;
			set_timer(&uac->request.retr_timer, RT_T2, 0);
		}
	} /* provisional replies */
	
done:
	/* we are done with the transaction, so unref it - the reference
	 * was incremented by t_check() function -bogdan*/
	t_unref(p_msg);
	/* don't try to relay statelessly neither on success
	 * (we forwarded statefully) nor on error; on troubles, 
	 * simply do nothing; that will make the other party to 
	 * retransmit; hopefuly, we'll then be better off 
	 */
	_tm_branch_index = 0;
	return 0;
not_found:
	set_t(T_UNDEFINED);
	return 1;
}
Beispiel #24
0
static void run_reqin_callbacks_internal(struct tmcb_head_list* hl,
							struct cell *trans, struct tmcb_params* params)
{
	struct tm_callback    *cbp;
	avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to,
				*backup_uri_from, *backup_uri_to;
#ifdef WITH_XAVP
	sr_xavp_t **backup_xavps;
#endif

	if (hl==0 || hl->first==0) return;
	backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM,
			&trans->uri_avps_from );
	backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, 
			&trans->uri_avps_to );
	backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, 
			&trans->user_avps_from );
	backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, 
			&trans->user_avps_to );
	backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, 
			&trans->domain_avps_from);
	backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, 
			&trans->domain_avps_to);
#ifdef WITH_XAVP
	backup_xavps = xavp_set_list(&trans->xavps_list);
#endif
	for (cbp=(struct tm_callback*)hl->first; cbp; cbp=cbp->next)  {
		DBG("DBG: trans=%p, callback type %d, id %d entered\n",
			trans, cbp->types, cbp->id );
		params->param = &(cbp->param);
		cbp->callback( trans, cbp->types, params );
	}
	set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, backup_uri_to );
	set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, backup_uri_from );
	set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, backup_dom_to );
	set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, backup_dom_from );
	set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, backup_to );
	set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, backup_from );
#ifdef WITH_XAVP
	xavp_set_list(backup_xavps);
#endif
}
Beispiel #25
0
void async_http_cb(struct http_m_reply *reply, void *param)
{
	async_query_t *aq;
	cfg_action_t *act;
	unsigned int tindex;
	unsigned int tlabel;
	struct cell *t = NULL;
	char *p;
	sip_msg_t *fmsg;

	if (reply->result != NULL) {
		LM_DBG("query result = %.*s [%d]\n", reply->result->len, reply->result->s, reply->result->len);
	}

	/* clean process-local result variables */
	ah_error.s = NULL;
	ah_error.len = 0;
	memset(ah_reply, 0, sizeof(struct sip_msg));

	/* set process-local result variables */
	if (reply->result == NULL) {
		/* error */
		ah_error.s = reply->error;
		ah_error.len = strlen(ah_error.s);
	} else {
		/* success */
		
		/* check for HTTP Via header
     	 * - HTTP Via format is different that SIP Via
     	 * - workaround: replace with Hia to be ignored by SIP parser
     	 */
    	if((p=strfindcasestrz(reply->result, "\nVia:"))!=NULL)
    	{
        	p++;
        	*p = 'H';
        	LM_DBG("replaced HTTP Via with Hia [[\n%.*s]]\n", reply->result->len, reply->result->s);
    	}

		ah_reply->buf = reply->result->s;
		ah_reply->len = reply->result->len;

		if (parse_msg(reply->result->s, reply->result->len, ah_reply) != 0) {
			LM_DBG("failed to parse the http_reply\n");
		} else {
			LM_DBG("successfully parsed http reply %p\n", ah_reply);
		}
	}

	aq = param;
	strncpy(q_id, aq->id, strlen(aq->id));
	
	act = (cfg_action_t*)aq->param;

	if (aq->query_params.suspend_transaction) {
		tindex = aq->tindex;
		tlabel = aq->tlabel;

		if (tmb.t_lookup_ident(&t, tindex, tlabel) < 0) {
			LM_ERR("transaction not found %d:%d\n", tindex, tlabel);
			LM_DBG("freeing query %p\n", aq);
			free_async_query(aq);
			return;
		}
		// we bring the list of AVPs of the transaction to the current context
		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
		set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
		set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
		set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

		if (t)
			tmb.unref_cell(t);

		LM_DBG("resuming transaction (%d:%d)\n", tindex, tlabel);

		if(act!=NULL)
			tmb.t_continue(tindex, tlabel, act);
	} else {
		fmsg = faked_msg_next();
		if (run_top_route(act, fmsg, 0)<0)
			LM_ERR("failure inside run_top_route\n");
	}

	free_sip_msg(ah_reply);
	free_async_query(aq);

	return;
}
Beispiel #26
0
/* run reply route functions */
int run_reply_route(struct sip_msg *_rpl, struct cell *_t, int index)
{
	avp_list_t	*backup_uri_from, *backup_uri_to;
	avp_list_t	*backup_user_from, *backup_user_to;
	avp_list_t	*backup_domain_from, *backup_domain_to;
	struct run_act_ctx	ra_ctx;

	if (!_t || (index < 0)) return -1;

	/* set the avp_list the one from transaction */
	backup_uri_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &_t->uri_avps_from );
	backup_uri_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &_t->uri_avps_to );
	backup_user_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &_t->user_avps_from );
	backup_user_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &_t->user_avps_to );
	backup_domain_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &_t->domain_avps_from );
	backup_domain_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &_t->domain_avps_to );

	init_run_actions_ctx(&ra_ctx);
	if (run_actions(&ra_ctx, onreply_rt.rlist[index], _rpl)<0)
		LOG(L_ERR, "ERROR: run_reply_route(): on_reply processing failed\n");

	/* restore original avp list */
	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_URI, backup_uri_from );
	set_avp_list( AVP_TRACK_TO | AVP_CLASS_URI, backup_uri_to );
	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_USER, backup_user_from );
	set_avp_list( AVP_TRACK_TO | AVP_CLASS_USER, backup_user_to );
	set_avp_list( AVP_TRACK_FROM | AVP_CLASS_DOMAIN, backup_domain_from );
	set_avp_list( AVP_TRACK_TO | AVP_CLASS_DOMAIN, backup_domain_to );

	return 0;
}
Beispiel #27
0
void run_trans_callbacks_internal(struct tmcb_head_list* cb_lst, int type,
									struct cell *trans, 
									struct tmcb_params *params)
{
	struct tm_callback    *cbp;
	avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to, *backup_uri_from, *backup_uri_to;
#ifdef WITH_XAVP
	sr_xavp_t **backup_xavps;
#endif

	backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM,
			&trans->uri_avps_from );
	backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, 
			&trans->uri_avps_to );
	backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, 
			&trans->user_avps_from );
	backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, 
			&trans->user_avps_to );
	backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, 
			&trans->domain_avps_from);
	backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, 
			&trans->domain_avps_to);
#ifdef WITH_XAVP
	backup_xavps = xavp_set_list(&trans->xavps_list);
#endif

	cbp=(struct tm_callback*)cb_lst->first;
	while(cbp){
		membar_depends(); /* make sure the cache has the correct cbp 
							 contents */
		if ( (cbp->types)&type ) {
			DBG("DBG: trans=%p, callback type %d, id %d entered\n",
				trans, type, cbp->id );
			params->param = &(cbp->param);
			cbp->callback( trans, type, params );
		}
		cbp=cbp->next;
	}
	set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, backup_dom_to );
	set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, backup_dom_from );
	set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, backup_to );
	set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, backup_from );
	set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, backup_uri_to );
	set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, backup_uri_from );
#ifdef WITH_XAVP
	xavp_set_list(backup_xavps);
#endif
}
Beispiel #28
0
/* function triggered from reactor in order to continue the processing
 */
int t_resume_async(int fd, void *param)
{
	static struct sip_msg faked_req;
	static struct ua_client uac;
	async_ctx *ctx = (async_ctx *)param;
	struct cell *backup_t;
	struct usr_avp **backup_list;
	struct socket_info* backup_si;
	struct cell *t= ctx->t;
	int route;

	LM_DBG("resuming on fd %d, transaction %p \n",fd, t);

	if (current_processing_ctx) {
		LM_CRIT("BUG - a context already set!\n");
		abort();
	}

	/* prepare for resume route */
	uac.br_flags = getb0flags( t->uas.request ) ;
	uac.uri = *GET_RURI( t->uas.request );
	if (!fake_req( &faked_req /* the fake msg to be built*/,
		t->uas.request, /* the template msg saved in transaction */
		&t->uas, /*the UAS side of the transaction*/
		&uac, /* the fake UAC */
		1 /* copy dst_uri too */)
	) {
		LM_ERR("fake_req failed\n");
		return 0;
	}

	/* enviroment setting */
	current_processing_ctx = ctx->msg_ctx;
	backup_t = get_t();
	/* fake transaction */
	set_t( t );
	reset_kr();
	set_kr(ctx->kr);
	/* make available the avp list from transaction */
	backup_list = set_avp_list( &t->user_avps );
	/* set default send address to the saved value */
	backup_si = bind_address;
	bind_address = t->uac[0].request.dst.send_sock;

	async_status = ASYNC_DONE; /* assume default status as done */
	/* call the resume function in order to read and handle data */
	return_code = ctx->resume_f( fd, &faked_req, ctx->resume_param );
	if (async_status==ASYNC_CONTINUE) {
		/* do not run the resume route */
		goto restore;
	}

	/* remove from reactor, we are done */
	reactor_del_reader( fd, -1, IO_FD_CLOSING);

	if (async_status == ASYNC_DONE_CLOSE_FD)
		close(fd);

	/* run the resume_route (some type as the original one) */
	swap_route_type(route, ctx->route_type);
	run_resume_route( ctx->resume_route, &faked_req);
	set_route_type(route);

	/* no need for the context anymore */
	shm_free(ctx);

restore:
	/* restore original environment */
	set_t(backup_t);
	/* restore original avp list */
	set_avp_list( backup_list );
	bind_address = backup_si;

	free_faked_req( &faked_req, t);
	current_processing_ctx = NULL;

	return 0;
}