Exemplo n.º 1
0
/**
 * Creates a new s_dialog structure.
 * Does not add the structure to the list
 * @param call_id - call_id of the dialog
 * @param aor - aor of the user
 * @param dir - the direction
 * @returns the new s_dialog* or NULL s_dialog
 */
s_dialog* new_s_dialog(str call_id,str aor, enum s_dialog_direction dir)
{
	s_dialog *d;
	
	if (!s_dialog_count_increment()) return 0;
	d = shm_malloc(sizeof(s_dialog));
	if (!d) {
		LOG(L_ERR,"ERR:"M_NAME":new_s_dialog(): Unable to alloc %d bytes\n",
			sizeof(s_dialog));
		goto error;
	}
	memset(d,0,sizeof(s_dialog));
	
	d->hash = get_s_dialog_hash(call_id);		
	STR_SHM_DUP(d->call_id,call_id,"shm");
	STR_SHM_DUP(d->aor,aor,"shm");	
	d->direction = dir;
	d->is_releasing = 0;
	return d;
error:
out_of_memory:
	if (d){
		shm_free(d);		
	}
	s_dialog_count_decrement();
	return 0;
}
Exemplo n.º 2
0
/**
 * Creates a new p_dialog structure.
 * Does not add the structure to the list.
 * @param call_id - call-id of the dialog
 * @param host - host that originates/terminates this dialog
 * @param port - port that originates/terminates this dialog
 * @param transport - transport that originates/terminates this dialog
 * @returns the new p_dialog* on success, or NULL on error;
 */
p_dialog* new_p_dialog(str call_id,str host,int port, int transport)
{
	p_dialog *d;
	
	if (!p_dialog_count_increment()) return 0;
	d = shm_malloc(sizeof(p_dialog));
	if (!d) {
		LOG(L_ERR,"ERR:"M_NAME":new_p_dialog(): Unable to alloc %d bytes\n",
			sizeof(p_dialog));
		goto error;
	}
	memset(d,0,sizeof(p_dialog));
	
	d->hash = get_p_dialog_hash(call_id);		
	STR_SHM_DUP(d->call_id,call_id,"shm");
	STR_SHM_DUP(d->host,host,"shm");	
	d->port = port;
	d->transport = transport;
				
	return d;
error:
out_of_memory:
	if (d){
		if (d->call_id.s) shm_free(d->call_id.s);
		if (d->host.s) shm_free(d->host.s);
		shm_free(d);		
	}
	p_dialog_count_decrement();
	return 0;
}
Exemplo n.º 3
0
/**
 * Creates a new lrf_dialog structure.
 * Does not add the structure to the list.
 * @param call_id - call-id of the dialog
 * @param target_uri - target of the dialog
 * @returns the new lrf_dialog* on success, or NULL on error;
 */
lrf_dialog* new_lrf_dialog(str call_id, str target_uri)
{
	lrf_dialog *d;
	
	if (!lrf_dialog_count_increment()) return 0;
	d = shm_malloc(sizeof(lrf_dialog));
	if (!d) {
		LOG(L_ERR,"ERR:"M_NAME":new_lrf_dialog(): Unable to alloc %d bytes\n",
			sizeof(lrf_dialog));
		goto error;
	}
	memset(d,0,sizeof(lrf_dialog));
	
	d->hash = get_lrf_dialog_hash(call_id);		
	STR_SHM_DUP(d->call_id,call_id,"shm");
	if(target_uri.len>0 && target_uri.s!=NULL)
		STR_SHM_DUP(d->target_uri, target_uri, "shm");
				
	return d;
error:
out_of_memory:
	if (d){
		if (d->call_id.s) shm_free(d->call_id.s);
		if (d->target_uri.s) shm_free(d->target_uri.s);
		shm_free(d);		
	}
	lrf_dialog_count_decrement();
	return 0;
}
Exemplo n.º 4
0
/*!
 * \brief Create and initialize new record structure
 * \param _dom domain name
 * \param _aor address of record
 * \param _r pointer to the new record
 * \return 0 on success, negative on failure
 */
int new_impurecord(str* _dom, str* public_identity, int reg_state, int barring, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, impurecord_t** _r) {
    *_r = (impurecord_t*) shm_malloc(sizeof (impurecord_t));
    if (*_r == 0) {
        LM_ERR("no more shared memory\n");
        return -1;
    }
    memset(*_r, 0, sizeof (impurecord_t));

    //setup callback list
    (*_r)->cbs = (struct ulcb_head_list*) shm_malloc(
            sizeof (struct ulcb_head_list));
    if ((*_r)->cbs == 0) {
        LM_CRIT("no more shared mem\n");
        shm_free(*_r);
        *_r = 0;
        return -2;
    }
    (*_r)->cbs->first = 0;
    (*_r)->cbs->reg_types = 0;

    (*_r)->public_identity.s = (char*) shm_malloc(public_identity->len);
    if ((*_r)->public_identity.s == 0) {
        LM_ERR("no more shared memory\n");
        shm_free(*_r);
        *_r = 0;
        return -2;
    }
    memcpy((*_r)->public_identity.s, public_identity->s, public_identity->len);
    (*_r)->public_identity.len = public_identity->len;
    (*_r)->domain = _dom;
    (*_r)->aorhash = core_hash(public_identity, 0, 0);
    (*_r)->reg_state = reg_state;
    if (barring >= 0) { //just in case we call this with no barring -1 will ignore
        (*_r)->barring = barring;
    }
    (*_r)->send_sar_on_delete = 1; /*defaults to 1 */
    if (ccf1 && ccf1->len > 0) STR_SHM_DUP((*_r)->ccf1, *ccf1, "CCF1");
    if (ccf2 && ccf2->len > 0) STR_SHM_DUP((*_r)->ccf2, *ccf2, "CCF2");
    if (ecf1 && ecf1->len > 0) STR_SHM_DUP((*_r)->ecf1, *ecf1, "ECF1");
    if (ecf2 && ecf2->len > 0) STR_SHM_DUP((*_r)->ecf2, *ecf2, "ECF2");
    /*assign ims subscription profile*/
    if (*s) {
        (*_r)->s = *s;
        lock_get((*_r)->s->lock);
        (*_r)->s->ref_count++;
        lock_release((*_r)->s->lock);
    }

    return 0;

out_of_memory:
    LM_ERR("no more shared memory\n");
    return -3;
}
Exemplo n.º 5
0
/**
 * Creates a registrar ipsec container.
 * This does not insert it in the registrar
 * the strings are duplicated in shm
 * @param spi_uc - SPI for UserEndpoint Client
 * @param spi_us - SPI for UserEndpoint Server
 * @param spi_pc - SPI for P-CSCF Client
 * @param spi_ps - SPI for UserEndpoint Server
 * @param port_uc - port for UserEndpoint Client
 * @param port_us - port for UserEndpoint Server
 * @param ealg_setkey - Cypher Algorithm
 * @param r_ealg - received Cypher Algorithm
 * @param ck_esp - Cypher Key
 * @param r_alg - received Integrity Algorithm
 * @param ik_esp - Integrity Key
 * @param prot - The IPSec protocol (either 'ah' or 'esp')
 * @param mod - The IPSec mode (either 'transport' or 'tunnel')
 * @returns the new r_ipsec* container or NULL on error
 */
r_ipsec* new_r_ipsec(unsigned int spi_uc,unsigned int spi_us,unsigned int spi_pc,unsigned int spi_ps,unsigned short int port_uc,unsigned short int port_us,
	str ealg_setkey,str r_ealg, str ck_esp,str alg_setkey,str r_alg, str ik_esp, str prot, str mod)
{
	r_ipsec *ipsec;
	
	ipsec = shm_malloc(sizeof(r_ipsec));
	if (!ipsec) {
		LOG(L_ERR,"ERR:"M_NAME":new_r_ipsec(): Unable to alloc %d bytes\n",
			sizeof(r_ipsec));
		return 0;
	}
	memset(ipsec,0,sizeof(r_ipsec));
	
	ipsec->spi_uc = spi_uc;
	ipsec->spi_us = spi_us;
	ipsec->spi_pc = spi_pc;
	ipsec->spi_ps = spi_ps;
	ipsec->port_uc = port_uc;
	ipsec->port_us = port_us;
	
	
	STR_SHM_DUP(ipsec->ealg,ealg_setkey,"new_r_ipsec");
	STR_SHM_DUP(ipsec->r_ealg,r_ealg,"new_r_ipsec");
	STR_SHM_DUP(ipsec->alg,alg_setkey,"new_r_ipsec");
	STR_SHM_DUP(ipsec->r_alg,r_alg,"new_r_ipsec");
	STR_SHM_DUP(ipsec->ck,ck_esp,"new_r_ipsec");
	STR_SHM_DUP(ipsec->ik,ik_esp,"new_r_ipsec");
	STR_SHM_DUP(ipsec->prot,prot,"new_r_ipsec");
	STR_SHM_DUP(ipsec->mod,mod,"new_r_ipsec");
			
	return ipsec;
out_of_memory:
	if (ipsec) free_r_ipsec(ipsec);
	return 0;	
}
Exemplo n.º 6
0
/**
 * Save the Record-routes for a dialog.
 * @param msg - the SIP message to extract RRs from
 * @param str1 - the direction to know if to reverse the RR list or not
 * @param d - dialog to save to
 */
void save_dialog_routes(struct sip_msg* msg, char* str1,p_dialog *d)
{
	int i;
	rr_t *rr,*ri;	
	struct hdr_field *hdr;
	if (d->routes){
		for(i=0;i<d->routes_cnt;i++)
			shm_free(d->routes[i].s);
		shm_free(d->routes);
		d->routes = 0;
	}
	d->routes_cnt = 0;
	for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){
		rr = (rr_t*)hdr->parsed;
		for(ri=rr;ri;ri=ri->next)
			d->routes_cnt++;
	}
	d->routes = shm_malloc(sizeof(str)*d->routes_cnt);
	if (!d->routes){
		LOG(L_ERR,"ERR:"M_NAME":save_dialog_routes(): Unable to alloc %d bytes\n",
			sizeof(str)*d->routes_cnt);
		d->routes_cnt = 0;
		return;		
	}
	if (!str1) return;
	if (str1[0]=='o'||str1[0]=='0'||str1[0]=='O'){
		/* originating - reverse order */
		i = d->routes_cnt-1;
		for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){
			rr = (rr_t*)hdr->parsed;
			for(ri=rr;ri;ri=ri->next){
				STR_SHM_DUP(d->routes[i],ri->nameaddr.uri,"shm");
				i--;
			}
		}
	}else{
		/* terminating - normal order */
		i = 0;
		for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){
			rr = (rr_t*)hdr->parsed;
			for(ri=rr;ri;ri=ri->next){
				STR_SHM_DUP(d->routes[i],ri->nameaddr.uri,"shm");
				i++;
			}
		}
	}		
out_of_memory:
	return;	
}
/**
 * Creates a subscription based on the given parameters.
 * @param req_uri - the AOR of the user to subcribe to
 * @param from - the From header
 * @param duration - expires time in seconds
 * @param asserted_identity - P-Asserted-Identity-Header to use
 * @returns the r_notification or NULL on error
 */
r_subscription* new_r_subscription(str req_uri,int duration)
{
	r_subscription *s=0;
	
	s = shm_malloc(sizeof(r_subscription));
	if (!s){
		LOG(L_ERR,"ERR:"M_NAME":new_r_subscription: Error allocating %d bytes\n",
			sizeof(r_subscription));
		goto error;
	}
	memset(s,0,sizeof(r_subscription));
	
	STR_SHM_DUP(s->req_uri,req_uri,"new_r_subscription");
	if (!s->req_uri.s) goto error;
		
	s->duration = duration;
	s->expires = 0;
	
	return s;
error:
out_of_memory:
	if (s->req_uri.s) shm_free(s->req_uri.s);
	if (s) shm_free(s);	
	return 0;
}
Exemplo n.º 8
0
/**
 * Creates a registrar public id subscriber 
 * This does not insert it in the registrar
 * @param subscriber - the contact of the subscribption - the subscriber
 * @param event - what event to subscribe to
 * @param expires - time of expiration
 * @param dialog - dialog for the subscription
 * @returns the r_subscriber created, NULL on error
 */
r_subscriber* new_r_subscriber(str subscriber,int event,int expires,dlg_t *dialog)
{
	r_subscriber *s;
	
	s = shm_malloc(sizeof(r_subscriber));
	if (!s) {
		LOG(L_ERR,"ERR:"M_NAME":new_r_subscriber(): Unable to alloc %d bytes\n",
			sizeof(r_subscriber));
		goto error;
	}
	memset(s,0,sizeof(r_subscriber));
	
	STR_SHM_DUP(s->subscriber,subscriber,"new_r_subscriber");
	
	s->event = event;
	
	s->expires = expires;

	s->dialog = dialog;
					
	return s;
error:
	if (s){
		if (s->subscriber.s) shm_free(s->subscriber.s);
		shm_free(s);		
	}
	return 0;
}
Exemplo n.º 9
0
/**
 * Creates a registrar contact 
 * This does not insert it in the registrar
 * @param host - the host part of the contact, in string
 * @param port - the port number of the contact
 * @param transport - the transport of the contact
 * @param uri - URI of the contact
 * @param reg_state - Registration state
 * @param expires - expires in
 * @param service_route - array of service routes
 * @param service_route_cnt - the size of the array above
 * @returns the new r_contact* or NULL on error
 */
r_contact* new_r_contact(str host,int port,int transport,str uri,enum Reg_States reg_state,int expires,
	str *service_route,int service_route_cnt, r_reg_type sos_flag)
{
	r_contact *c;
	int i;
	
	c = shm_malloc(sizeof(r_contact));
	if (!c) {
		LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n",
			sizeof(r_contact));
		goto error;
	}
	memset(c,0,sizeof(r_contact));
	
	STR_SHM_DUP(c->host,host,"new_r_contact");
	c->port = port;
	c->transport = transport;
	c->hash = get_contact_hash(host,port,transport,r_hash_size);
	STR_SHM_DUP(c->uri,uri,"new_r_contact");		
	c->reg_state = reg_state;
	c->expires = expires;	
	c->sos_flag = sos_flag;
		
	if (service_route_cnt && service_route){
		c->service_route = shm_malloc(service_route_cnt*sizeof(str));
		if (!c->service_route){
			LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n",
				service_route_cnt*sizeof(str));
			goto error;
		}
		for(i=0;i<service_route_cnt;i++)
			STR_SHM_DUP(c->service_route[i],service_route[i],"new_r_contact");
		c->service_route_cnt = service_route_cnt;
	}
		
	return c;
error:
out_of_memory:
	if (c){
		free_r_contact(c);			
	}
	return 0;
}
Exemplo n.º 10
0
/**
 * Saves a dialog.
 * @param msg - the initial request
 * @param str1 - direction - "orig" or "term"
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error 
 */
int S_save_dialog(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id;
	s_dialog *d;
	str aor;
	str uri,tag;
	str ruri;	
	enum s_dialog_direction dir = get_dialog_direction(str1);
	
	if (!find_dialog_aor(msg,dir,&aor)){
		LOG(L_ERR,"ERR:"M_NAME":S_save_dialog(): Error retrieving %s contact\n",str1);
		return CSCF_RETURN_BREAK;
	}		
		
	call_id = cscf_get_call_id(msg,0);
	if (!call_id.len)
		return CSCF_RETURN_FALSE;

	LOG(L_INFO,"DBG:"M_NAME":S_save_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s);

	if (is_s_dialog(call_id,aor)){
		LOG(L_ERR,"ERR:"M_NAME":S_save_dialog: dialog already exists!\n");	
		return CSCF_RETURN_FALSE;
	}
	
	d = add_s_dialog(call_id,aor,dir);
	if (!d) return CSCF_RETURN_FALSE;

	d->method = get_dialog_method(msg->first_line.u.request.method);
	STR_SHM_DUP(d->method_str,msg->first_line.u.request.method,"shm");
	d->first_cseq = cscf_get_cseq(msg,0);
	d->last_cseq = d->first_cseq;
	d->state = DLG_STATE_INITIAL;
	d->expires = d_act_time()+60;
	
	cscf_get_from_tag(msg,&tag);
	cscf_get_from_uri(msg,&uri);
	ruri=cscf_get_identity_from_ruri(msg);
	 
	tmb.new_dlg_uac(&call_id,
						&tag,
						d->first_cseq,&uri,
						&ruri,
						&d->dialog_c);
	
	tmb.new_dlg_uas(msg,99,&d->dialog_s);

	d_unlock(d->hash);
	
//	print_s_dialogs(L_INFO);
	
	return CSCF_RETURN_TRUE;	
}
Exemplo n.º 11
0
r_security *new_r_security(str sec_header,r_security_type type,float q)
{
	r_security *s=0;

	s = shm_malloc(sizeof(r_security));
	if (!s){
		LOG(L_ERR,"ERR:"M_NAME":save_contact_security: Error allocating %d bytes.\n",sizeof(r_security));
		goto error ;
	}
	memset(s,0,sizeof(r_security));
	
	s->type = type;
	s->q = q;
	STR_SHM_DUP(s->sec_header,sec_header,"save_contact_security");
	if (!s->sec_header.s) goto error;	
	return s;
error:
out_of_memory:
	if (s) shm_free(s);
	return 0;
}
Exemplo n.º 12
0
scscf_list* new_scscf_list(str call_id,scscf_entry *sl)
{
	scscf_list *l;
	
	l = shm_malloc(sizeof(scscf_list));
	if (!l) {
		LOG(L_ERR,"ERR:"M_NAME":new_scscf_list(): Unable to alloc %d bytes\n",
			sizeof(scscf_list));
		goto error;
	}
	memset(l,0,sizeof(scscf_list));
	
	STR_SHM_DUP(l->call_id,call_id,"shm");
	l->list = sl;
				
	return l;
error:
out_of_memory:
	if (l){
		shm_free(l);		
	}
	return 0;
}
Exemplo n.º 13
0
/**
 * Creates a notification based on the given parameters
 * @param req_uri - the Request-URI for the NOTIFY
 * @param uri - uri to send to
 * @param subscription_state - the Subscription-State header value
 * @param event - the event
 * @param content_type - content type
 * @param content - content
 * @param dialog - dialog to send on
 * @returns the r_notification or NULL on error
 */
r_notification* new_r_notification(str req_uri,str uri,str subscription_state,str event,
					str content_type,str content,dlg_t *dialog,int version)
{
	r_notification *n=0;
	str buf;	
	char bufc[MAX_REGINFO_SIZE];
	
	n = shm_malloc(sizeof(r_notification));
	if (!n){
		LOG(L_ERR,"ERR:"M_NAME":new_r_notification: Error allocating %d bytes\n",
			sizeof(r_notification));
		goto error;
	}
	memset(n,0,sizeof(r_notification));
	
	STR_SHM_DUP(n->req_uri,req_uri,"new_r_notification");
	
	STR_SHM_DUP(n->uri,uri,"new_r_notification");
	
	STR_SHM_DUP(n->subscription_state,subscription_state,"new_r_notification");
	
	STR_SHM_DUP(n->event,event,"new_r_notification");
	
	STR_SHM_DUP(n->content_type,content_type,"new_r_notification");
	
	sprintf(bufc,content.s,version);
	buf.s = bufc;
	buf.len = strlen(bufc);
	STR_SHM_DUP(n->content,buf,"new_r_notification");
	
	n->dialog = dialog;
	
	return n;
error:
out_of_memory:
	free_r_notification(n);
	return 0;
}
Exemplo n.º 14
0
int new_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c)
{
	int i, has_rinstance=0;
	ppublic_t* ppublic_ptr;
	int is_default = 1, params_len;
	struct sip_uri sip_uri;
        char* p, *params, *sep;
        str rinstance = {0,0};
        
	*_c = (pcontact_t*)shm_malloc(sizeof(pcontact_t) + _contact->len + _ci->received_host.len + _ci->via_host.len);
	if (*_c == 0) {
		LM_ERR("no more shared memory\n");
		return -1;
	}
	memset(*_c, 0, sizeof(pcontact_t));

	LM_DBG("New contact [<%.*s>] with %d associated IMPUs in state: [%s]\n",
			_contact->len, _contact->s,
			_ci->num_public_ids,
			reg_state_to_string(_ci->reg_state));
        
        

        p = (char*)((struct pcontact*)(*_c) + 1);
        (*_c)->aor.s = p;
	memcpy(p, _contact->s, _contact->len);
        p += _contact->len;
	(*_c)->aor.len = _contact->len;
	(*_c)->domain = (str*)_d;

	if (parse_uri((*_c)->aor.s, (*_c)->aor.len, &sip_uri) != 0) {
		LM_ERR("unable to determine contact host from uri [%.*s\n", (*_c)->aor.len, (*_c)->aor.s);
		shm_free((*_c)->aor.s);
		shm_free(*_c);
		*_c = 0;
		return -2;
	}
        
        /* is there an rinstance param */
        LM_DBG("checking for rinstance");
        /*check for alias - NAT */
        params = sip_uri.sip_params.s;
        params_len = sip_uri.sip_params.len;
        while (params_len >= RINSTANCE_LEN) {
            if (strncmp(params, RINSTANCE, RINSTANCE_LEN) == 0) {
                has_rinstance = 1;
                break;
            }
            sep = memchr(params, 59 /* ; */, params_len);
            if (sep == NULL) {
                LM_DBG("no rinstance param\n");
                break;
            } else {
                params_len = params_len - (sep - params + 1);
                params = sep + 1;
            }
        }
        if (has_rinstance) {
            rinstance.s = params + RINSTANCE_LEN;
            rinstance.len = params_len - RINSTANCE_LEN;
            sep = (char*)memchr(rinstance.s, 59 /* ; */, rinstance.len);
            if (sep != NULL){
                rinstance.len = (sep-rinstance.s);
            }
        }
        (*_c)->rinstance.s = rinstance.s;
        (*_c)->rinstance.len = rinstance.len;
	(*_c)->contact_host.s = sip_uri.host.s;
	(*_c)->contact_host.len = sip_uri.host.len;
	(*_c)->contact_port = sip_uri.port_no?sip_uri.port_no:5060;
	(*_c)->contact_user.s = sip_uri.user.s;
	(*_c)->contact_user.len = sip_uri.user.len;

	(*_c)->expires = _ci->expires;
	(*_c)->reg_state = _ci->reg_state;

	// Add received Info:
	if (_ci->received_host.len > 0 && _ci->received_host.s) {
        (*_c)->received_host.s = p;
		memcpy(p, _ci->received_host.s, _ci->received_host.len);
                p += _ci->received_host.len;
		(*_c)->received_host.len = _ci->received_host.len;
		(*_c)->received_port = _ci->received_port;
		(*_c)->received_proto = _ci->received_proto;
	}
        
        if (_ci->via_host.len > 0 && _ci->via_host.s) {
            (*_c)->via_host.s = p;
            memcpy(p, _ci->via_host.s, _ci->via_host.len);
            p += _ci->via_host.len;
            (*_c)->via_host.len = _ci->via_host.len;
            (*_c)->via_port = _ci->via_port;
            (*_c)->via_proto = _ci->via_prot;
        }
        
        (*_c)->aorhash = get_aor_hash(_d, &_ci->via_host, _ci->via_port, _ci->via_prot);

	//setup public ids
	for (i=0; i<_ci->num_public_ids; i++) {
		if (i>0) is_default = 0; //only the first one is default - P-Associated-uri (first one is default)
		if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr)!=0) {
			LM_ERR("unable to create new ppublic\n");
		} else {
			insert_ppublic(*_c, ppublic_ptr);
		}
	}
	//add the service routes
	if (_ci->num_service_routes > 0) {
		(*_c)->service_routes = shm_malloc(_ci->num_service_routes * sizeof(str));
		if (!(*_c)->service_routes) {
			LM_ERR("no more shm mem\n");
			goto out_of_memory;
		} else {
			for (i = 0; i < _ci->num_service_routes; i++) {
				STR_SHM_DUP((*_c)->service_routes[i], _ci->service_routes[i], "new_pcontact");
			}
			(*_c)->num_service_routes = _ci->num_service_routes;
		}
	}
        
        LM_DBG("New contact host:port [%.*s:%d]\n", (*_c)->contact_host.len, (*_c)->contact_host.s, (*_c)->contact_port);
        LM_DBG("New contact via host:port:proto: [%.*s:%d:%d]\n", (*_c)->via_host.len, (*_c)->via_host.s, (*_c)->via_port, (*_c)->via_proto);
        LM_DBG("New contact received host:port:proto: [%.*s:%d:%d]\n", (*_c)->received_host.len, (*_c)->received_host.s, (*_c)->received_port, (*_c)->received_proto);
        LM_DBG("New contact aorhash [%u]\n", (*_c)->aorhash);
        
	return 0;

out_of_memory:
	return -1;
}
Exemplo n.º 15
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);
}
Exemplo n.º 16
0
int update_pcontact(struct udomain* _d, struct pcontact_info* _ci, struct pcontact* _c) //TODO: should prob move this to pcontact
{
	int is_default = 1;
	ppublic_t* ppublic_ptr;
	int i;

	_c->reg_state = _ci->reg_state;

	if (_ci->expires > 0) {
		_c->expires = _ci->expires;
	}

	if (_ci->num_service_routes > 0 && _ci->service_routes) {
		//replace all existing service routes
		if (_c->service_routes) { //remove old service routes
			for (i=0; i<_c->num_service_routes; i++) {
				if (_c->service_routes[i].s)
					shm_free(_c->service_routes[i].s);
				shm_free(_c->service_routes);
				_c->service_routes=0;
				_c->num_service_routes=0;
			}
		}
		//now add the new service routes
		if (_ci->num_service_routes > 0) {
			_c->service_routes = shm_malloc(_ci->num_service_routes*sizeof(str));
			if (!_c->service_routes) {
				LM_ERR("no more shm mem trying to allocate [%ld bytes]\n", _ci->num_service_routes*sizeof(str));
				goto out_of_memory;
			} else {
				for (i=0; i<_ci->num_service_routes; i++) {
					STR_SHM_DUP(_c->service_routes[i], _ci->service_routes[i], "update_pcontact");
				}
				_c->num_service_routes = _ci->num_service_routes;
			}
		}
	}

	if (_ci->num_public_ids > 0 && _ci->public_ids) {
		if (_c->head) {
			LM_DBG("ppublic's already exist.... .not updating\n");
		} else {
			for (i = 0; i < _ci->num_public_ids; i++) {
				if (i > 0)
					is_default = 0; //only the first one is default - P-Associated-uri (first one is default)
				if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr) != 0) {
					LM_ERR("unable to create new ppublic\n");
				} else {
					insert_ppublic(_c, ppublic_ptr);
				}
			}
		}
	}

	// update received info (if info is available):
	if (_ci->received_host.len > 0) {
		if (_c->received_host.s)
			shm_free(_c->received_host.s);
		STR_SHM_DUP(_c->received_host, _ci->received_host, "update_pcontact");
	}
	if (_ci->received_port > 0) _c->received_port = _ci->received_port;
	if (_ci->received_proto > 0) _c->received_proto = _ci->received_proto;

	//TODO: update path, etc
	run_ul_callbacks(PCSCF_CONTACT_UPDATE, _c);
	return 0;

out_of_memory:
	return -1;
}
Exemplo n.º 17
0
/**
 * Updates a dialog.
 * If the initial request was:
 * - INVITE - refreshes the expiration or looks for the BYE and destroys the dialog 
 * if found
 * - SUBSCRIBE - looks for the Subscription-state in NOTIFY, refreshes the expiration 
 * and if terminated destroys the dialog
 * - When adding more dialogs, add the refreshal methods here or they will expire and will
 * be destroyed. Also add the termination to reduce the memory consumption and improve the
 * performance.
 * @param msg - the request/response
 * @param str1 - direction - "orig" or "term"
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error 
 */
int P_update_dialog(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id;
	p_dialog *d;
	int response;
	int cseq;
	struct hdr_field *h=0;
	struct sip_msg *req=0;
	str host;
	int port,transport;
	int expires;
	str totag;
	time_t t_time=0;
	str ses_exp = {0,0};
	str refresher = {0,0};
	enum p_dialog_direction dir;
	
	dir = get_dialog_direction(str1);
	
	if (msg->first_line.type==SIP_REPLY) req = cscf_get_request_from_reply(msg);
	else req = msg;
	if (!find_dialog_contact(req,dir,&host,&port,&transport)){
		LOG(L_ERR,"ERR:"M_NAME":P_update_dialog(%s): Error retrieving %s contact\n",str1,str1);
		return CSCF_RETURN_BREAK;
	}		
		
	call_id = cscf_get_call_id(msg,0);
	if (!call_id.len)
		return CSCF_RETURN_FALSE;

	LOG(L_DBG,"DBG:"M_NAME":P_update_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s);

	d = get_p_dialog(call_id,host,port,transport,&dir);
	if (!d)
		d = get_p_dialog(call_id,host,port,transport,0);
	if (!d){
		if (msg->first_line.type==SIP_REQUEST &&
			msg->first_line.u.request.method.len == 3 && 
			strncasecmp(msg->first_line.u.request.method.s,"ACK",3)){
			/* to skip the ACK after a 4xx when the dialog was dropped already*/
			return CSCF_RETURN_TRUE;
		}else{
			LOG(L_CRIT,"ERR:"M_NAME":P_update_dialog: dialog does not exists!\n");
			return CSCF_RETURN_FALSE;
		}	
	}


	if (msg->first_line.type==SIP_REQUEST){
		/* Request */
		LOG(L_DBG,"DBG:"M_NAME":P_update_dialog(%s): Method <%.*s> \n",str1,
			msg->first_line.u.request.method.len,msg->first_line.u.request.method.s);
		cseq = cscf_get_cseq(msg,&h);
		if (cseq>d->last_cseq) d->last_cseq = cseq;
		if (get_dialog_method(msg->first_line.u.request.method) == DLG_METHOD_INVITE)
		{
			d->uac_supp_timer = supports_extension(msg, &str_ext_timer);
	
			ses_exp = cscf_get_session_expires_body(msg, &h);
			t_time = cscf_get_session_expires(ses_exp, &refresher);
			if (!t_time){
				d->expires = d_act_time()+pcscf_dialogs_expiration_time;
				d->lr_session_expires = 0;
			} else {
				d->expires = d_act_time() + t_time;
				d->lr_session_expires = t_time;
				if (refresher.len)
					STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER");
			}
		}
		else if (d->method == DLG_METHOD_SUBSCRIBE && 
			msg->first_line.u.request.method.len == 6 && 
			strncasecmp(msg->first_line.u.request.method.s,"NOTIFY",6)==0)
		{
			// Subscription-State header is mandatory for NOTIFY. See RFC 3265, Section 7.2
			expires = cscf_get_subscription_state(msg);
			if (expires >= 0)
			{
				d->expires = d_act_time()+expires;
			}
			else
			{
				d->expires = d_act_time()+pcscf_dialogs_expiration_time;
			}
		}
		else
		{
			expires = cscf_get_expires_hdr(msg);
			if (expires >= 0) 
			{
				LOG(L_INFO,"DBG:"M_NAME":P_update_dialog(%.*s): Update expiration time to %d via Expire header 2\n",call_id.len,call_id.s,expires);
				d->expires = d_act_time()+expires;
			}
			else
			{
				LOG(L_INFO,"INF:"M_NAME": update_dialog(%.*s): d->expires+=pcscf_dialogs_expiration_time 4\n",call_id.len,call_id.s);
				d->expires = d_act_time()+pcscf_dialogs_expiration_time;
			}
			d->lr_session_expires = 0;		
		}
	}else{
		/* Reply */
		response = msg->first_line.u.reply.statuscode;
		LOG(L_DBG,"DBG:"M_NAME":P_update_dialog(%s): <%d> \n",str1,response);
		cseq = cscf_get_cseq(msg,&h);
		if (cseq==0 || h==0) return CSCF_RETURN_FALSE;
		if (d->first_cseq==cseq && d->method_str.len == ((struct cseq_body *)h->parsed)->method.len &&
			strncasecmp(d->method_str.s,((struct cseq_body *)h->parsed)->method.s,d->method_str.len)==0 &&
			d->state < DLG_STATE_CONFIRMED){
			/* reply to initial request */
			if (response<200 && response>100){
				save_dialog_routes(msg,str1,d);
				d->state = DLG_STATE_EARLY;
				d->expires = d_act_time()+300;
				cscf_get_to_tag(msg,&totag);
				tmb.update_dlg_uas(d->dialog_s,response,&totag);
				tmb.dlg_response_uac(d->dialog_c,msg,IS_NOT_TARGET_REFRESH);
			}else
			if (response>=200 && response<300){
				save_dialog_routes(msg,str1,d);
				d->state = DLG_STATE_CONFIRMED;
				
				update_dialog_on_reply(msg, d);
				
				cscf_get_to_tag(msg,&totag);
				tmb.update_dlg_uas(d->dialog_s,response,&totag);
				tmb.dlg_response_uac(d->dialog_c,msg,IS_NOT_TARGET_REFRESH);
				
			}else
				if (response>300){
					d->state = DLG_STATE_TERMINATED;
					d_unlock(d->hash);				
					return P_drop_dialog(msg,str1,str2);
				}				
		}else{
			/* reply to subsequent request */			
			if (!req) req = cscf_get_request_from_reply(msg);
			
			/* destroy dialogs on specific methods */
			switch (d->method){
				case DLG_METHOD_OTHER:							
					expires = cscf_get_expires_hdr(msg);
					if (expires >= 0)
					{
						d->expires = d_act_time()+expires;
					}
					else
					{
						d->expires = d_act_time()+pcscf_dialogs_expiration_time;
					}
					d->lr_session_expires = 0;
					break;
				case DLG_METHOD_INVITE:
					if (req && req->first_line.u.request.method.len==3 &&
						strncasecmp(req->first_line.u.request.method.s,"BYE",3)==0){
						d->state = DLG_STATE_TERMINATED;
						d_unlock(d->hash);				
						return P_drop_dialog(msg,str1,str2);
					}
					update_dialog_on_reply(msg, d);
					break;
				case DLG_METHOD_SUBSCRIBE:
//					if (req && req->first_line.u.request.method.len==9 &&
//						strncasecmp(req->first_line.u.request.method.s,"SUBSCRIBE",9)==0 &&
//						cscf_get_expires_hdr(msg)==0){						
//						d->state = DLG_STATE_TERMINATED;
//						d_unlock(d->hash);				
//						return P_drop_dialog(msg,str1,str2);
//					}
					if (req && req->first_line.u.request.method.len==6 &&
						strncasecmp(req->first_line.u.request.method.s,"NOTIFY",6)==0){
						expires = cscf_get_subscription_state(req);
						if (expires==0){						
							d->state = DLG_STATE_TERMINATED;
							d_unlock(d->hash);				
							return P_drop_dialog(msg,str1,str2);
						}else if (expires>0){
							d->expires = d_act_time() + expires;
						}
					}
					break;
			}
			if (cseq>d->last_cseq) d->last_cseq = cseq;
		}
	}
	
	d_unlock(d->hash);
	
	print_p_dialogs(L_INFO);
	
	return CSCF_RETURN_TRUE;	
out_of_memory:
	d_unlock(d->hash);
	return CSCF_RETURN_ERROR;	
}
Exemplo n.º 18
0
/**
 * Updates a dialog.
 * If the initial request was:
 * - INVITE - refreshes the expiration or looks for the BYE and destroys the dialog 
 * if found
 * - SUBSCRIBE - looks for the Subscription-state in NOTIFY, refreshes the expiration 
 * and if terminated destroys the dialog
 * - When adding more dialogs, add the refreshal methods here or they will expire and will
 * be destroyed. Also add the termination to reduce the memory consumption and improve the
 * performance.
 * @param msg - the request/response
 * @param str1 - direction - "orig" or "term"
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error 
 */
int S_update_dialog(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id;
	s_dialog *d;
	int response;
	int cseq;

	struct hdr_field *h=0;
	struct sip_msg *req=0;
	int expires=0;
	str totag;
	time_t t_time;
	str ses_exp = {0,0};
	str refresher = {0,0};

	enum s_dialog_direction dir = get_dialog_direction(str1);
		
//	if (!find_dialog_aor(msg,str1,&aor)){
//		req = cscf_get_request_from_reply(msg);		
//		if (!find_dialog_aor(req,str1,&aor)){
//			LOG(L_ERR,"ERR:"M_NAME":S_update_dialog(%s): Error retrieving %s contact\n",str1,str1);
//			return CSCF_RETURN_BREAK;
//		}
//	}		
		
	call_id = cscf_get_call_id(msg,0);
	if (!call_id.len)
		return CSCF_RETURN_FALSE;

	LOG(L_DBG,"DBG:"M_NAME":S_update_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s);

	d = get_s_dialog_dir(call_id,dir);
//	if (!d && msg->first_line.type==SIP_REPLY){
//		/* Try to get the dialog from the request */
//		if (!req) req = cscf_get_request_from_reply(msg);		
//		if (!find_dialog_aor(req,str1,&aor)){
//			LOG(L_ERR,"ERR:"M_NAME":S_update_dialog(%s): Error retrieving %s contact\n",str1,str1);
//			return CSCF_RETURN_BREAK;
//		}		
//		d = get_s_dialog_dir(call_id,aor);		
//	}
	if (!d){
		LOG(L_INFO,"INFO:"M_NAME":S_update_dialog: dialog does not exists!\n");	
		return CSCF_RETURN_FALSE;
	}


	if (msg->first_line.type==SIP_REQUEST){
		/* Request */
		LOG(L_DBG,"DBG:"M_NAME":S_update_dialog(%s): Method <%.*s> \n",str1,
			msg->first_line.u.request.method.len,msg->first_line.u.request.method.s);
		cseq = cscf_get_cseq(msg,&h);
		if (cseq>d->last_cseq) d->last_cseq = cseq;
		if (get_dialog_method(msg->first_line.u.request.method) == DLG_METHOD_INVITE)
		{
			d->uac_supp_timer = supports_extension(msg, &str_ext_timer);
	
			ses_exp = cscf_get_session_expires_body(msg, &h);
			t_time = cscf_get_session_expires(ses_exp, &refresher);
			if (!t_time)
			{
				d->expires = d_act_time()+scscf_dialogs_expiration_time;
				d->lr_session_expires = 0;
			}
			else
			{
				d->expires = d_act_time() + t_time;
				d->lr_session_expires = t_time;
				if (refresher.len)
					STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER");
			}
		}
		else if (d->method == DLG_METHOD_SUBSCRIBE &&
			msg->first_line.u.request.method.len == 6 &&
			strncasecmp(msg->first_line.u.request.method.s,"NOTIFY",6)==0)
		{
			// Subscription-State header is mandatory for NOTIFY. See RFC 3265, Section 7.2
			expires = cscf_get_subscription_state(msg);
			if (expires >= 0)
				d->expires = d_act_time()+expires;
			else
				d->expires = d_act_time()+scscf_dialogs_expiration_time;
		}
		else
		{
			expires = cscf_get_expires_hdr(msg,0);
			if (expires >= 0)
			        d->expires = d_act_time()+expires;
			else
					d->expires = d_act_time()+scscf_dialogs_expiration_time;
	
			d->lr_session_expires = 0;		
		}
	}else{
		/* Reply */
		response = msg->first_line.u.reply.statuscode;
		LOG(L_DBG,"DBG:"M_NAME":S_update_dialog(%s): <%d> \n",str1,response);
		cseq = cscf_get_cseq(msg,&h);
		if (cseq==0 || h==0) return CSCF_RETURN_FALSE;
		if (d->first_cseq==cseq && d->method_str.len == ((struct cseq_body *)h->parsed)->method.len &&
			strncasecmp(d->method_str.s,((struct cseq_body *)h->parsed)->method.s,d->method_str.len)==0 &&
			d->state < DLG_STATE_CONFIRMED){
			/* reply to initial request */
			if (response<200){
				d->state = DLG_STATE_EARLY;
				d->expires = d_act_time()+300;
			}else
			if (response>=200 && response<300){
				d->state = DLG_STATE_CONFIRMED;
				update_dialog_on_reply(msg, d);
				
				/*I save the dialogs only here because
				 * i only want to release confirmed dialogs*/
				cscf_get_to_tag(msg,&totag);
				if (d->dialog_s){
					tmb.update_dlg_uas(d->dialog_s,response,&totag);
					tmb.dlg_response_uac(d->dialog_c,msg,IS_NOT_TARGET_REFRESH);
				}else{
					LOG(L_ERR,"ERR:S_update_dialog(): dialog_s for dialog was NULL!\n");
				}
			}else
				if (response>300){
					d->state = DLG_STATE_TERMINATED;
					d_unlock(d->hash);				
					struct cell * t = tmb.t_gett();
					if(t->nr_of_outgoings < 2)
						return S_drop_dialog(msg,str1,str2);
				}				
		}else{
			/* reply to subsequent request */			
			if (!req) req = cscf_get_request_from_reply(msg);
			
			/* destroy dialogs on specific methods */
			switch (d->method){
				case DLG_METHOD_OTHER:							
					d->expires = d_act_time()+scscf_dialogs_expiration_time;
					d->lr_session_expires = 0;
					break;
				
				case DLG_METHOD_INVITE:
					if (req && req->first_line.u.request.method.len==3 &&
						strncasecmp(req->first_line.u.request.method.s,"BYE",3)==0){
						d->state = DLG_STATE_TERMINATED;
						d_unlock(d->hash);				
						return S_drop_dialog(msg,str1,str2);
					}
					update_dialog_on_reply(msg, d);
					break;
				case DLG_METHOD_SUBSCRIBE:
//					if (req && req->first_line.u.request.method.len==9 &&
//						strncasecmp(req->first_line.u.request.method.s,"SUBSCRIBE",9)==0 &&
//						cscf_get_expires_hdr(msg)==0){						
//						d->state = DLG_STATE_TERMINATED;
//						d_unlock(d->hash);				
//						return P_dros_dialog(msg,str1,str2);
//					}
					if (req && req->first_line.u.request.method.len==6 &&
						strncasecmp(req->first_line.u.request.method.s,"NOTIFY",6)==0){
						expires = cscf_get_subscription_state(req);
						if (expires==0){						
							d->state = DLG_STATE_TERMINATED;
							d_unlock(d->hash);				
							return S_drop_dialog(msg,str1,str2);
						}else if (expires>0){
							d->expires = d_act_time() + expires;
						}
					}
					else if (req && req->first_line.u.request.method.len==9 &&
						strncasecmp(req->first_line.u.request.method.s,"SUBSCRIBE",9)==0){
						expires = cscf_get_expires_hdr(msg,0);
						if (expires >= 0)
							d->expires = d_act_time()+expires;
						else
							d->expires = d_act_time()+scscf_dialogs_expiration_time;
					}					
					break;
			}
			if (cseq>d->last_cseq) d->last_cseq = cseq;						
		}
	}
	
	d_unlock(d->hash);
	
	print_s_dialogs(L_INFO);
	
	return CSCF_RETURN_TRUE;	
out_of_memory:
	if (d) d_unlock(d->hash);
	return CSCF_RETURN_ERROR;	
}
Exemplo n.º 19
0
/* update an existing impurecord. if one doesnt exist it will be created.
 * make sure yuo lock the domain before calling this and unlock it afterwards
 * return: 0 on success, -1 on failure
 */
int update_impurecord(struct udomain* _d, str* public_identity, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r) {
    int res;

    res = get_impurecord(_d, public_identity, _r);
    if (res != 0) {
        if (reg_state != IMPU_NOT_REGISTERED && s) {
            LM_DBG("No existing impu record for <%.*s>.... creating new one\n", public_identity->len, public_identity->s);
            res = insert_impurecord(_d, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1, ecf2, _r);

            //for the first time we create an IMPU we must set the primary record (we don't worry about it on updates - ignored)
            (*_r)->is_primary = is_primary; //TODO = this should prob move to insert_impurecord fn

            if (reg_state == IMPU_UNREGISTERED) {
                //update unreg expiry so the unreg record is not stored 'forever'
                (*_r)->expires = time(NULL) + unreg_validity;
            }
            if (res != 0) {
                LM_ERR("Unable to insert new IMPU for <%.*s>\n", public_identity->len, public_identity->s);
                return -1;
            } else {
                run_ul_callbacks(NULL, UL_IMPU_INSERT, *_r, NULL);
                return 0;
            }
        } else {
            LM_DBG("no IMPU found to update and data not valid to create new one - not a problem record was probably removed as it has no contacts\n");
            return 0;
        }

    }

    //if we get here, we have a record to update
    LM_DBG("updating IMPU record with public identity for <%.*s>\n", public_identity->len, public_identity->s);
    (*_r)->reg_state = reg_state;
    if (reg_state == IMPU_UNREGISTERED) {
        //update unreg expiry so the unreg record is not stored 'forever'
        (*_r)->expires = time(NULL) + unreg_validity;
    }
    if (barring >= 0) (*_r)->barring = barring;
    
    if (send_sar_on_delete >= 0) (*_r)->send_sar_on_delete = send_sar_on_delete;
    
    if (ccf1) {
        if ((*_r)->ccf1.s)
            shm_free((*_r)->ccf1.s);
        STR_SHM_DUP((*_r)->ccf1, *ccf1, "SHM CCF1");
    }
    if (ccf2) {
        if ((*_r)->ccf2.s)
            shm_free((*_r)->ccf2.s);
        STR_SHM_DUP((*_r)->ccf2, *ccf2, "SHM CCF2");
    }
    if (ecf1) {
        if ((*_r)->ecf1.s)
            shm_free((*_r)->ecf1.s);
        STR_SHM_DUP((*_r)->ecf1, *ecf1, "SHM ECF1");
    }
    if (ecf2) {
        if ((*_r)->ecf2.s)
            shm_free((*_r)->ecf2.s);
        STR_SHM_DUP((*_r)->ecf2, *ecf2, "SHM ECF2");
    }

    if (s) {
        LM_DBG("we have a new ims_subscription\n");
        if ((*_r)->s) {
            lock_get((*_r)->s->lock);
            if ((*_r)->s->ref_count == 1) {
                LM_DBG("freeing user data as no longer referenced\n");
                free_ims_subscription_data((*_r)->s); //no need to release lock after this. its gone ;)
                (*_r)->s = 0;
            } else {
                (*_r)->s->ref_count--;
                LM_DBG("new ref count for ims sub is %d\n", (*_r)->s->ref_count);
                lock_release((*_r)->s->lock);
            }
        }
        (*_r)->s = *s;
        lock_get((*_r)->s->lock);
        (*_r)->s->ref_count++;
        lock_release((*_r)->s->lock);
    }

    run_ul_callbacks((*_r)->cbs, UL_IMPU_UPDATE, *_r, NULL);
    return 0;

out_of_memory:
    unlock_udomain(_d, public_identity);
    return -1;
}
Exemplo n.º 20
0
/**
 * Updates the r_contact with the new states
 * If not found, it will be inserted
 * \note Aquires the lock on the hash_slot on success, so release it when you are done.
 * @param host - the host part of the contact, in string
 * @param port - the port number of the contact
 * @param transport - the transport of the contact
 * @param uri - URI of the contact
 * @param reg_state - Registration state
 * @param expires - expires in
 * @param service_route - array of service routes
 * @param service_route_cnt - the size of the array above
 * @param pinhole - NAT pin hole
 * @param sos_flag - flag for Emergency Registration
 * @returns the updated added r_contact, 0 on error
 */
r_contact* update_r_contact(str host,int port,int transport,
	str *uri,enum Reg_States *reg_state,int *expires,str **service_route,
	int *service_route_cnt, r_nat_dest **pinhole, int *sos_flag)
{
	r_contact *c=0;
	int i;
	r_reg_type sos_mask;

	if(sos_flag && (*sos_flag>0))
		sos_mask = EMERG_REG;
	else	sos_mask = NORMAL_REG;

	c = get_r_contact(host,port,transport, sos_mask);
	if (!c){
		if (uri&&reg_state && expires && service_route && service_route_cnt)
			return pinhole?add_r_contact(host,port,transport,*uri,*reg_state,*expires,*service_route,*service_route_cnt, *pinhole, sos_mask):
					   add_r_contact(host,port,transport,*uri,*reg_state,*expires,*service_route,*service_route_cnt, 0,  sos_mask);
		else return 0;
	}else{
		/* first drop the old temporary public ids */
		if (c->reg_state==DEREGISTERED && reg_state && *reg_state==REGISTERED){
			while(c->head){
				del_r_public(c,c->head);
			}
		}

		if (uri) {
			if (c->uri.s) shm_free(c->uri.s);
			STR_SHM_DUP(c->uri,*uri,"update_r_contact");
		}
		if (reg_state) c->reg_state = *reg_state;
		if (expires) c->expires = *expires;
		if (service_route){
			if (c->service_route){
				for(i=0;i<c->service_route_cnt;i++)
					if (c->service_route[i].s) shm_free(c->service_route[i].s);
				shm_free(c->service_route);
				c->service_route=0;
				c->service_route_cnt=0;
			}
			if (*service_route&&*service_route_cnt){
				c->service_route = shm_malloc((*service_route_cnt)*sizeof(str));
				if (!c->service_route){
					LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n",
						(*service_route_cnt)*sizeof(str));					
					goto out_of_memory;					
				}else{
					for(i=0;i<*service_route_cnt;i++)
						STR_SHM_DUP(c->service_route[i],(*service_route)[i],"new_r_contact");
					c->service_route_cnt = *service_route_cnt;											
				}			
			}
		}
		if (pinhole) c->pinhole = *pinhole;
		c->sos_flag = sos_mask;
		return c;
	}
	
out_of_memory:
	return c;	
}
Exemplo n.º 21
0
/**
 * Saves a dialog.
 * @param msg - the initial request
 * @param str1 - direction - "orig" or "term"
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error 
 */
int S_save_dialog(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id;
	s_dialog *d;
	str aor;
	char buf1[256],buf2[256];
	str uri,tag,ruri,x;	
	time_t t_time;
	str ses_exp = {0,0};
	str refresher = {0,0};
	str event = {0,0};
	struct hdr_field *h;
	unsigned int hash;
	
	enum s_dialog_direction dir = get_dialog_direction(str1);
	
	if (!find_dialog_aor(msg,dir,&aor)){
		LOG(L_ERR,"ERR:"M_NAME":S_save_dialog(): Error retrieving %s contact\n",str1);
		return CSCF_RETURN_BREAK;
	}		
		
	call_id = cscf_get_call_id(msg,0);
	if (!call_id.len)
		return CSCF_RETURN_FALSE;

	LOG(L_INFO,"DBG:"M_NAME":S_save_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s);

	if (is_s_dialog(call_id,aor,dir)){
		LOG(L_ERR,"ERR:"M_NAME":S_save_dialog: dialog already exists!\n");	
		return CSCF_RETURN_TRUE;
	}
	
	d = add_s_dialog(call_id,aor,dir);
	if (!d) return CSCF_RETURN_FALSE;

	d->method = get_dialog_method(msg->first_line.u.request.method);
	STR_SHM_DUP(d->method_str,msg->first_line.u.request.method,"shm");
	d->first_cseq = cscf_get_cseq(msg,0);
	d->last_cseq = d->first_cseq;
	d->state = DLG_STATE_INITIAL;

	d->uac_supp_timer = supports_extension(msg, &str_ext_timer);

	ses_exp = cscf_get_session_expires_body(msg, &h);
	t_time = cscf_get_session_expires(ses_exp, &refresher);
	if (!t_time) {
		d->expires = d_act_time() + 60;
		d->lr_session_expires = 0;
	} else {
		d->expires = d_act_time() + t_time;
		d->lr_session_expires = t_time;
		if (refresher.len)
			STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER");
	}
	
	cscf_get_from_tag(msg,&tag);
	cscf_get_from_uri(msg,&x);
	uri.len = snprintf(buf1,256,"<%.*s>",x.len,x.s);
	uri.s = buf1;	
	cscf_get_to_uri(msg,&x);
	ruri.len = snprintf(buf2,256,"<%.*s>",x.len,x.s);
	ruri.s = buf2;
	 
	tmb.new_dlg_uac(&call_id,
						&tag,
						d->first_cseq,&uri,
						&ruri,
						&d->dialog_c);
	
	tmb.new_dlg_uas(msg,99,&d->dialog_s);
	
	event = cscf_get_event(msg);
	if (event.len){
		STR_SHM_DUP(d->event,event,"shm");
	}
	else
		d->event = event;

	d_unlock(d->hash);
	
	print_s_dialogs(L_INFO);
	
	return CSCF_RETURN_TRUE;	
out_of_memory:
	if (d){
		hash = d->hash;
		del_s_dialog(d);
		d_unlock(hash);
	}
	return CSCF_RETURN_ERROR;	
}
Exemplo n.º 22
0
/**
 * Updates the r_public with the new reg_state and ims_subscription values, with a previous lock on the registrar.
 * If not found, it will be inserted.
 * \note Aquires the lock on the hash_slot on success and if the lock is different from previous_lock, so release it
 *  when you are done and if different then from previous lock.
 * @param aor - the address of record
 * @param locked_hash - the previous lock on the registrar
 * @param reg_state - new registration state, NULL if no update necessary
 * @param s - the new subscription attached, NULL if no update necessary
 * @returns the update r_public or NULL on error
 */
r_public* update_r_public_previous_lock(str aor,int locked_hash,enum Reg_States *reg_state,ims_subscription **s,
	str *ccf1, str *ccf2, str *ecf1, str *ecf2)
{
	r_public *p=0;
	p = get_r_public_previous_lock(aor,locked_hash);
	if (!p){
		if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){
			p = add_r_public_previous_lock(aor,locked_hash,*reg_state,*s);
			if (!p) return p;			
			if (ccf1) {
				if (p->ccf1.s) shm_free(p->ccf1.s);
				STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1");
			}
			if (ccf2) {
				if (p->ccf2.s) shm_free(p->ccf2.s);
				STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2");
			}
			if (ecf1) {
				if (p->ecf1.s) shm_free(p->ecf1.s);
				STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1");
			}
			if (ecf2) {
				if (p->ecf2.s) shm_free(p->ecf2.s);
				STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2");
			}
			return p;
		}
		else return 0;
	}else{
		if (reg_state) p->reg_state = *reg_state;
		if (*s) {
			if (p->s){
				lock_get(p->s->lock);
				if (p->s->ref_count==1){
					free_user_data(p->s);
				}else{
					p->s->ref_count--;
					lock_release(p->s->lock);
				}
			}			
			p->s = *s;
			lock_get(p->s->lock);
				p->s->ref_count++;
			lock_release(p->s->lock);
		}
		if (ccf1) {
			if (p->ccf1.s) shm_free(p->ccf1.s);
			STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1");
		}
		if (ccf2) {
			if (p->ccf2.s) shm_free(p->ccf2.s);
			STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2");
		}
		if (ecf1) {
			if (p->ecf1.s) shm_free(p->ecf1.s);
			STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1");
		}
		if (ecf2) {
			if (p->ecf2.s) shm_free(p->ecf2.s);
			STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2");
		}
		return p;
	}
out_of_memory:
	return p;	
}
Exemplo n.º 23
0
int new_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c)
{
	int i;
	ppublic_t* ppublic_ptr;
	int is_default = 1;
	struct sip_uri sip_uri;


	*_c = (pcontact_t*)shm_malloc(sizeof(pcontact_t));
	if (*_c == 0) {
		LM_ERR("no more shared memory\n");
		return -1;
	}
	memset(*_c, 0, sizeof(pcontact_t));

	LM_DBG("New contact [<%.*s>] with %d associated IMPUs in state: [%s]\n",
			_contact->len, _contact->s,
			_ci->num_public_ids,
			reg_state_to_string(_ci->reg_state));

	(*_c)->aor.s = (char*) shm_malloc(_contact->len);
	if ((*_c)->aor.s == 0) {
		LM_ERR("no more shared memory\n");
		shm_free(*_c);
		*_c = 0;
		return -2;
	}
	memcpy((*_c)->aor.s, _contact->s, _contact->len);
	(*_c)->aor.len = _contact->len;
	(*_c)->domain = (str*)_d;

	if (parse_uri((*_c)->aor.s, (*_c)->aor.len, &sip_uri) != 0) {
		LM_ERR("unable to determine contact host from uri [%.*s\n", (*_c)->aor.len, (*_c)->aor.s);
		shm_free((*_c)->aor.s);
		shm_free(*_c);
		*_c = 0;
		return -2;
	}
	(*_c)->contact_host.s = sip_uri.host.s;
	(*_c)->contact_host.len = sip_uri.host.len;
	(*_c)->contact_port = sip_uri.port_no;
	(*_c)->contact_user.s = sip_uri.user.s;
	(*_c)->contact_user.len = sip_uri.user.len;

	if (hashing_type==0) {
		(*_c)->aorhash = core_hash(_contact, 0, 0);
	} else {
		(*_c)->aorhash = core_hash(&(*_c)->contact_host, 0, 0);
	}
	(*_c)->expires = _ci->expires;
	(*_c)->reg_state = _ci->reg_state;

	// Add received Info:
	if (_ci->received_host.len > 0 && _ci->received_host.s) {
		(*_c)->received_host.s = (char*) shm_malloc(_ci->received_host.len);
		if ((*_c)->received_host.s == 0) {
			LM_ERR("no more share memory\n");
			shm_free((*_c)->aor.s);
			shm_free(*_c);
			*_c = 0;
			return -2;
		}
		memcpy((*_c)->received_host.s, _ci->received_host.s, _ci->received_host.len);
		(*_c)->received_host.len = _ci->received_host.len;
		(*_c)->received_port = _ci->received_port;
		(*_c)->received_proto = _ci->received_proto;
	}

	//setup public ids
	for (i=0; i<_ci->num_public_ids; i++) {
		if (i>0) is_default = 0; //only the first one is default - P-Associated-uri (first one is default)
		if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr)!=0) {
			LM_ERR("unable to create new ppublic\n");
		} else {
			insert_ppublic(*_c, ppublic_ptr);
		}
	}
	//add the service routes
	if (_ci->num_service_routes > 0) {
		(*_c)->service_routes = shm_malloc(_ci->num_service_routes * sizeof(str));
		if (!(*_c)->service_routes) {
			LM_ERR("no more shm mem\n");
			goto out_of_memory;
		} else {
			for (i = 0; i < _ci->num_service_routes; i++) {
				STR_SHM_DUP((*_c)->service_routes[i], _ci->service_routes[i], "new_pcontact");
			}
			(*_c)->num_service_routes = _ci->num_service_routes;
		}
	}
	return 0;

out_of_memory:
	return -1;
}
Exemplo n.º 24
0
/**
 * Updates the r_public with the new reg_state and ims_subscription values.
 * If not found, it will be inserted.
 * \note Aquires the lock on the hash_slot on success, so release it when you are done.
 * @param aor - the address of record
 * @param reg_state - new registration state, NULL if no update necessary
 * @param s - the new subscription attached, NULL if no update necessary
 * @returns the update r_public or NULL on error
 */
r_public* update_r_public(str aor,enum Reg_States *reg_state,ims_subscription **s,
	str *ccf1, str *ccf2, str *ecf1, str *ecf2)
{
	r_public *p=0;
	//LOG(L_CRIT,"update_r_public():with aor %.*s\n",aor.len,aor.s);
	
	if ((*s)->wpsi) {
		p = get_r_public_wpsi(aor);
	} else {
		p = get_r_public(aor);
	}
	
	if (!p){
		//LOG(L_DBG,"updating a new r_public profile\n");			 
		if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){
			p = add_r_public(aor,*reg_state,*s);
			
			if (!p) return p;			
			if (ccf1) {
				if (p->ccf1.s) shm_free(p->ccf1.s);
				STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1");
			}
			if (ccf2) {
				if (p->ccf2.s) shm_free(p->ccf2.s);
				STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2");
			}
			if (ecf1) {
				if (p->ecf1.s) shm_free(p->ecf1.s);
				STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1");
			}
			if (ecf2) {
				if (p->ecf2.s) shm_free(p->ecf2.s);
				STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2");
			}
			//LOG(L_DBG,"update_r_public():  it was actually adding\n");
			return p;
		}
		else return 0;
	}else{
		//LOG(L_DBG,"updating a not so new r_public profile\n");		
		if (reg_state) p->reg_state = *reg_state;
		if (*s) {
			
			if (p->s){
				lock_get(p->s->lock);
				if (p->s->ref_count==1){
					free_user_data(p->s);
				}else{
					p->s->ref_count--;
					lock_release(p->s->lock);
				}
			}			
			p->s = *s;
			lock_get(p->s->lock);
				p->s->ref_count++;
			lock_release(p->s->lock);
			
			
			 if ((*s)->wpsi)
			 {	
			 	
			 	 p->s=NULL; 
			 	 			 	 
			 	 if (p->prev) p->prev->next=p->next;
			 	 else registrar[r_hash_size].head=p->next;	
			 	 if (p->next) p->next->prev=p->prev;
			 	 else registrar[r_hash_size].tail=p->prev;
			 	 
			 	 free_r_public(p);
			 	 r_unlock(r_hash_size);			 
			 	 p=add_r_public(aor,0,*s);
			 	 
			 }
			
			
		}
		if (ccf1) {
			if (p->ccf1.s) shm_free(p->ccf1.s);
			STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1");
		}
		if (ccf2) {
			if (p->ccf2.s) shm_free(p->ccf2.s);
			STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2");
		}
		if (ecf1) {
			if (p->ecf1.s) shm_free(p->ecf1.s);
			STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1");
		}
		if (ecf2) {
			if (p->ecf2.s) shm_free(p->ecf2.s);
			STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2");
		}
		//LOG(L_DBG,"update_r_public():    return normaly\n");
		return p;
	}
out_of_memory:
	return p;	
}