Пример #1
0
/**
 * Searches for a r_public record and returns it.
 * \note Aquires the lock on the hash slot on success, so release it when you are done.
 * @param aor - the address of record to look for
 * @returns - the r_public found, 0 if not found
 */
r_public* get_r_public(str aor)
{
	r_public *p=0;
	unsigned int hash;
	hash = get_aor_hash(aor,r_hash_size);
	r_lock(hash);
	p = registrar[hash].head;
	while(p){
		if (p->aor.len == aor.len &&
			strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
		p = p->next;
	}
	r_unlock(hash);
	
	/*
	 * Here i plan to put the function that tries to match the aor with the wPSI
	 * There might be an issue 
	 * if i return this locked, then i have to wait for the lock in the next one...
	 * mmmh... might be an issue
	 * */
	 if (scscf_support_wildcardPSI)
	 	return(get_matching_wildcard_psi(aor));
	 else
	 	return 0;
	 
}
Пример #2
0
/* return the slot id for inserting contacts in the hash */
unsigned int get_hash_slot(udomain_t* _d, str* via_host, unsigned short via_port, unsigned short via_proto) {
    unsigned int sl;

    sl = get_aor_hash(_d, via_host, via_port, via_proto);
    sl = sl & (_d->size - 1) ;
    LM_DBG("Returning hash slot: [%d]\n", sl);

    return sl;
}
Пример #3
0
/**
 * Searches for a r_public record and returns it.
 * \note Does NOT Aquire the lock on the hash_slot
 * \note Must be called with a lock on the hash
 * @param aor - the address of record to look for
 * @returns the r_public if found found or NULL if not found
 */
r_public* get_r_public_nolock(str aor)
{
	r_public *p=0;
	unsigned int hash;
	hash = get_aor_hash(aor,r_hash_size);
	p = registrar[hash].head;
	while(p){
		if (p->aor.len == aor.len &&
			strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
		p = p->next;
	}
	return 0;
}
Пример #4
0
/**
 * Searches for a r_public record and returns it.
 * \note Does NOT Aquire the lock on the hash_slot
 * \note Must be called with a lock on the hash
 * @param aor - the address of record to look for
 * @returns the r_public if found found or NULL if not found
 */
r_public* get_r_public_nolock(str aor)
{
	r_public *p=0;
	unsigned int hash;
	hash = get_aor_hash(aor,r_hash_size);
	p = registrar[hash].head;
	while(p){
		if (p->aor.len == aor.len &&
			strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
		p = p->next;
	}
	LOG(L_ERR,"no match found but get_r_public_nolock doesn't look in the WildCardedPSI area\n");
	return 0;
}
Пример #5
0
/**
 * Searches for a r_public record and returns, with a previous lock aquired.
 * \note Aquires the lock on the hash slot on success AND if the previous lock lock was not previously aquired,
 *  so release it when you are done, but be careful to only release it if the new lock!=previous_lock.
 * @param aor - the address of record to look for
 * @param locked_hash - previous lock, already aquired.
 * @returns - the r_public found, 0 if not found
 */
r_public* get_r_public_previous_lock(str aor,int locked_hash)
{
	r_public *p=0;
	unsigned int hash;
	hash = get_aor_hash(aor,r_hash_size);
	if (hash!=locked_hash) r_lock(hash);
	p = registrar[hash].head;
	while(p){
		if (p->aor.len == aor.len &&
			strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
		p = p->next;
	}
	if (hash!=locked_hash) r_unlock(hash);
	return 0;
}
Пример #6
0
/**
 * Creates a registrar r_public.
 * This does not insert it in the registrar
 * @param aor - the public identity as address of record
 * @param reg_state - desired registration state
 * @param s - the ims subscription to which this belongs
 * @returns - the r_public created, NULL on error
 */
r_public* new_r_public(str aor, enum Reg_States reg_state, ims_subscription *s)
{
	r_public *p;
	
	p = shm_malloc(sizeof(r_public));
	if (!p){
		LOG(L_ERR,"ERR:"M_NAME":new_r_public(): Unable to alloc %d bytes\n",
			sizeof(r_public));
		goto error;
	}	
	memset(p,0,sizeof(r_public));
	
	p->hash = get_aor_hash(aor,r_hash_size);
	
	p->aor.s = shm_malloc(aor.len);
	if (!p->aor.s){
		LOG(L_ERR,"ERR:"M_NAME":new_r_public(): Unable to alloc %d bytes\n",
			aor.len);
		goto error;
	}
	p->aor.len = aor.len;
	memcpy(p->aor.s,aor.s,aor.len);
	
	p->reg_state = reg_state;
	
	p->s = s;
	if (s) {
		lock_get(s->lock);
		s->ref_count++;
		lock_release(s->lock);
	}
		
	return p;
error:
	if (p){
		if (p->aor.s) shm_free(p->aor.s);	
		shm_free(p);
	}
	return 0;	
}
Пример #7
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;
}
Пример #8
0
/**
 *	Decode a r_public from a binary data structure
 * @param x - binary data to decode from
 * @returns the r_public* where the data has been decoded
 */
r_public* bin_decode_r_public(bin_data *x)
{
	r_public *p=0;
	r_contact *c=0,*cn=0;
	r_subscriber *s,*sn=0;
	int len,i;
	unsigned short k;
	char ch;
	str st;
	
	len = sizeof(r_public);
	p = (r_public*) shm_malloc(len);
	if (!p) {
		LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_public: Error allocating %d bytes.\n",len);
		goto error;
	}
	memset(p,0,len);
	
	if (!bin_decode_str(x,&st)||!str_shm_dup(&(p->aor),&st)) goto error;
	if (!bin_decode_str(x,&st)||!str_shm_dup(&(p->early_ims_ip),&st)) goto error;
	p->hash = get_aor_hash(p->aor,r_hash_size);
	if (!bin_decode_char(x,&ch)) goto error;
	p->reg_state = ch;
	
	p->s = bin_decode_ims_subscription(x);
	if (!p->s) goto error;
	
	if (!bin_decode_ushort(x,&k)) goto error;
	for(i=0;i<k;i++){
		c = bin_decode_r_contact(x);
		if (!c) goto error;
		c->prev = p->tail;
		c->next = 0;
		if (!p->head) p->head = c;
		if (p->tail) p->tail->next = c;
		p->tail = c;
	}

	if (!bin_decode_ushort(x,&k)) goto error;
	for(i=0;i<k;i++){
		s = bin_decode_r_subscriber(x);
		if (!s) goto error;
		s->prev = p->stail;
		s->next = 0;
		if (!p->shead) p->shead = s;
		if (p->stail) p->stail->next = s;
		p->stail = s;
	}
	
	return p;
error:
	LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_public: Error while decoding (at %d (%04x)).\n",x->max,x->max);
	if (p) {
		if (p->aor.s) shm_free(p->aor.s);
		while(p->head){
			c = p->head;
			cn = c->next;
			free_r_contact(c);
			p->head = cn;
		}
		while(p->shead){
			s = p->shead;
			sn = s->next;
			free_r_subscriber(s);
			p->shead = sn;
		}
		shm_free(p);
	}
	return 0;
}
Пример #9
0
/**
 * Creates the full reginfo XML.
 * @param pv - the r_public to create for
 * @param event_type - event type
 * @param subsExpires - subscription expiration
 * @returns the str with the XML content
 */
str r_get_reginfo_full(void *pv,int event_type,long *subsExpires)
{		
	str x={0,0};
	str buf,pad;	
	char bufc[MAX_REGINFO_SIZE],padc[MAX_REGINFO_SIZE];

	r_public *p=(r_public*)pv,*p2;
	r_contact *c;
	r_contact_param *cp;
	ims_public_identity *pi;
	int i,j;
	unsigned int hash;
	
	buf.s = bufc;
	buf.len=0;
	pad.s = padc;
	pad.len=0;
	
	*subsExpires = r_update_subscription_status(p);
	
	STR_APPEND(buf,xml_start);
	sprintf(pad.s,r_reginfo_s.s,"%d",r_full.len,r_full.s);
	pad.len = strlen(pad.s);
	STR_APPEND(buf,pad);
	
	
	if (p->s){
		for(i=0;i<p->s->service_profiles_cnt;i++)
			for(j=0;j<p->s->service_profiles[i].public_identities_cnt;j++){
				pi = &(p->s->service_profiles[i].public_identities[j]);
				if (!pi->barring){
					hash = get_aor_hash(pi->public_identity,r_hash_size);
					if (hash == p->hash) /* because we already have the lock on p->hash */
						p2 = get_r_public_nolock(pi->public_identity);
					else 
						p2 = get_r_public(pi->public_identity);
					if (p2){
						if (p2->reg_state==REGISTERED)
							sprintf(pad.s,registration_s.s,p2->aor.len,p2->aor.s,p2,r_active.len,r_active.s);
						else 
							sprintf(pad.s,registration_s.s,p2->aor.len,p2->aor.s,p2,r_terminated.len,r_terminated.s);
						pad.len = strlen(pad.s);
						STR_APPEND(buf,pad);
						c = p2->head;
						while(c){
							if(c->qvalue != -1) {
								float q = (float)c->qvalue/1000;
								sprintf(pad.s,contact_s_q.s,c,r_active.len,r_active.s,r_registered.len,r_registered.s,c->expires-time_now, q);
							}
							else
								sprintf(pad.s,contact_s.s,c,r_active.len,r_active.s,r_registered.len,r_registered.s,c->expires-time_now);
							pad.len = strlen(pad.s);
							STR_APPEND(buf,pad);							
							STR_APPEND(buf,uri_s);
							STR_APPEND(buf,c->uri);
							STR_APPEND(buf,uri_e);
							for(cp=c->parameters;cp;cp=cp->next){
								sprintf(pad.s,unknown_param_s.s,cp->name.len,cp->name.s);
								pad.len = strlen(pad.s);
								STR_APPEND(buf,pad);
								STR_APPEND(buf,cp->value);
								STR_APPEND(buf,unknown_param_e);
							}
							STR_APPEND(buf,contact_e);
							c = c->next;
						}
						STR_APPEND(buf,registration_e);
						if (p2->hash != p->hash) r_unlock(p2->hash);
					}
				}
			}				
	}

	STR_APPEND(buf,r_reginfo_e);

	
	x.s = pkg_malloc(buf.len+1);
	if (x.s){
		x.len = buf.len;
		memcpy(x.s,buf.s,buf.len);
		x.s[x.len]=0;
	}
	return x;
}
Пример #10
0
/* can't assume we are locked here */
int get_pcontact_by_src(udomain_t* _d, str * _host, unsigned short _port, unsigned short _proto, struct pcontact** _c) {
	int i;
	struct pcontact* c;
	unsigned int aorhash, sl;
	char c_contact[256], *p;
	str s_contact;

	if (hashing_type == 1) {//we hash on IP:PORT - so no need to search sequentially..
		/* get_aor_hash in this mode expects to see contact as host:port */
		memset(c_contact, 0, 256);
		memcpy(c_contact, _host->s, _host->len);
		p = c_contact + _host->len;
		*p = ':';
		p++;
		sprintf(p,"%d", _port);
		s_contact.s = c_contact;
		s_contact.len = strlen(c_contact);

		aorhash = get_aor_hash(_d, &s_contact);
		sl = aorhash & (_d->size - 1);
		c = _d->table[sl].first;

		for (i = 0; i < _d->table[sl].n; i++) {
			lock_ulslot(_d, i);
			LM_DBG("Searching for contact in P-CSCF usrloc [%.*s]\n",
					s_contact.len,
					s_contact.s);

			// First check, if Proto and Port matches:
			if ((c->received_port == _port) && (c->received_proto == _proto)) {
				LM_DBG("Received host len %d (search %d)\n", c->received_host.len, _host->len);
				// Then check the length:
				if (c->received_host.len == _host->len) {
					LM_DBG("Received host %.*s (search %.*s)\n",
							c->received_host.len, c->received_host.s,
							_host->len, _host->s);

					// Finally really compare the "received_host"
					if (!memcmp(c->received_host.s, _host->s, _host->len)) {
						*_c = c;
						return 0;
					}
				}
			}
			unlock_ulslot(_d, i);
		}
	} else {
		/* search sequentially */
		for(i=0; i<_d->size; i++)
		{
			c = _d->table[i].first;
			while(c) {
				LM_DBG("Port %d (search %d), Proto %d (search %d), reg_state %s (search %s)\n",
					c->received_port, _port, c->received_proto, _proto,
					reg_state_to_string(c->reg_state), reg_state_to_string(PCONTACT_REGISTERED)
					);
				// First check, if Proto and Port matches:
				if ((c->received_port == _port) && (c->received_proto == _proto)) {
					LM_DBG("Received host len %d (search %d)\n", c->received_host.len, _host->len);
					// Then check the length:
					if (c->received_host.len == _host->len) {
						LM_DBG("Received host %.*s (search %.*s)\n",
							c->received_host.len, c->received_host.s,
							_host->len, _host->s);

						// Finally really compare the "received_host"
						if (!memcmp(c->received_host.s, _host->s, _host->len)) {
							*_c = c;
							return 0;
						}
					}
				}
				c = c->next;
			}
		}
	}
	return 1; /* Nothing found */
}
Пример #11
0
int get_pcontact(udomain_t* _d, str* _contact, struct pcontact** _c) {
	unsigned int sl, i, aorhash, len, len2;
	struct pcontact* c;
	char *ptr, *ptr2;
	ppublic_t* impu;

	/* search in cache */
	aorhash = get_aor_hash(_d, _contact);
	sl = aorhash & (_d->size - 1);
	c = _d->table[sl].first;

	for (i = 0; i < _d->table[sl].n; i++) {
		LM_DBG("Searching for contact in P-CSCF usrloc [%.*s]\n",
				_contact->len,
				_contact->s);

		if ((c->aorhash == aorhash) && (c->aor.len == _contact->len)
				&& !memcmp(c->aor.s, _contact->s, _contact->len)) {
			*_c = c;
			return 0;
		}

		/* hash is correct, but contacts differ. Let's check if maybe the UA is using a different user part
		 * which was part of his implicit set
		 */
		ptr2 = ptr = _contact->s;

		if ((c->aorhash == aorhash)) {
			len2 = len = _contact->len;

			/* double check domain part is the same - this is to ensure that we don't false match on a collision that has a similar
			 * userpart in the list of impus... (very unlikely but safer this way).
			 */
			ptr = memchr(_contact->s, '@', _contact->len);
			if (ptr) {
				len = (ptr - _contact->s);
				ptr2 = ptr + 1;
				len2 = _contact->len - (ptr2 - _contact->s);
			}

			ptr = memchr(c->aor.s, '@', c->aor.len);
			if (!ptr)
				ptr = c->aor.s;
			else
				ptr = ptr + 1;

			if ((len2 <= c->aor.len) && (memcmp(ptr2, ptr, len2)==0)) {
				impu = c->head;
				while (impu) {
					LM_DBG("comparing first %d chars of impu [%.*s] for contact [%.*s]\n",
							len,
							impu->public_identity.len, impu->public_identity.s,
							_contact->len, _contact->s);
					if (memcmp(impu->public_identity.s, _contact->s, len) == 0) {
						//match
						*_c = c;
						return 0;
					}
					impu = impu->next;
				}
			}
		}
		c = c->next;
	}
	return 1; /* Nothing found */
}
Пример #12
0
 /**
  * In case of a Wildcarded PSI, it compiles the regexp for quick processing
  */
r_public* new_r_public(str aor, enum Reg_States reg_state, ims_subscription *s)
{
	r_public *p;
	
	/*I didn't want to make this so complicated..*/
	t_regexp_unit *newwpsi;
	char *temp=0;
	int i,j;
	//int len;
	//int errcode;
	
	p = shm_malloc(sizeof(r_public));
	if (!p){
		LOG(L_ERR,"ERR:"M_NAME":new_r_public(): Unable to alloc %d bytes\n",
			sizeof(r_public));
		goto error;
	}	
	memset(p,0,sizeof(r_public));
	if (s->wpsi !=1)
	{
		//very sensible thing to do...
		p->hash = get_aor_hash(aor,r_hash_size);
		
	} else {
		
		//here it gets a bit complicated
		
		/* if its a wildcarded psi....*/
		p->hash=r_hash_size;
		/*will be in the last slot*/
		p->regexp=shm_malloc(sizeof(t_regexp_list));
		p->regexp->head=NULL;
		p->regexp->tail=NULL;
		/*lets compile the regular expression and compile it..*/
		for (i=0;i<s->service_profiles_cnt;i++)
		{
			for (j=0;j<s->service_profiles[i].public_identities_cnt;j++)
			{
				if (s->service_profiles[i].public_identities[j].wildcarded_psi.s && s->service_profiles[i].public_identities[j].wildcarded_psi.len>0)
				 {
					// for each wildcardpsi we add a member to the regexp list in the r_public
					newwpsi=shm_malloc(sizeof(t_regexp_unit));
					newwpsi->next=NULL;
					newwpsi->prev=NULL;
					// now we have to deal with using an external function that expects
					// some string with a finishing \0 character
					//len=s->service_profiles[i].public_identities[j].wildcarded_psi.len;
					temp=escape_all_wildcards_and_copy(s->service_profiles[i].public_identities[j].wildcarded_psi);
					//temp=shm_malloc(len+1);
					//memcpy(temp,s->service_profiles[i].public_identities[j].wildcarded_psi.s,len);
					//temp[len]=0;
					LOG(L_DBG,"New_r_public : REGULAR EXPRESSION is %s\n\n",temp);
					/*errcode=regcomp(&(newwpsi->exp),temp,REG_ICASE|REG_EXTENDED|REG_NOSUB);
					if(errcode!=0)
					{
						// there was an error
						LOG(L_DBG,"there was at least ONE error in regcomp %i\n",errcode);
						//shm_free(temp); temp=NULL;
						len=regerror(errcode,&(newwpsi->exp),NULL,0);
						temp=shm_malloc(len);
						regerror(errcode,&(newwpsi->exp),temp,len);
						LOG(L_DBG,"and that was %s",temp);
						shm_free(temp); temp=NULL;
						
						shm_free(newwpsi);
						goto error;
					}*/
					newwpsi->s=temp;
					//LOG(L_DBG,"there was NO error in regcomp\n");
					//shm_free(temp); temp=NULL;
					newwpsi->prev=p->regexp->tail;
					if (p->regexp->tail)
					{
						p->regexp->tail->next=newwpsi;
						p->regexp->tail=newwpsi;
					} else {
						// no tail means no head too...
						p->regexp->head=newwpsi;
						p->regexp->tail=newwpsi;
					}
					
				}
			}
		}
		
		
		
			
		
	}
	//LOG(L_DBG,"after the mess inside new_r_public\n");
	p->aor.s = shm_malloc(aor.len); // I wonder if this should be done in the case of wildpsi
	if (!p->aor.s){
		LOG(L_ERR,"ERR:"M_NAME":new_r_public(): Unable to alloc %d bytes\n",
			aor.len);
		goto error;
	}
	p->aor.len = aor.len;
	memcpy(p->aor.s,aor.s,aor.len);
	
	p->reg_state = reg_state;
	
	p->s = s;
	if (s) {
		lock_get(s->lock);
		s->ref_count++;
		lock_release(s->lock);
	}
	//LOG(L_DBG,"new_r_public we are returning %p\n",p);	
	return p;
error:
	if (p){
		if (p->aor.s) shm_free(p->aor.s);
		// free the regexp list of shit!	
		if (p->regexp) free_regexp_list(&(p->regexp));
		//if (temp) shm_free(temp);
		shm_free(p);
	}
	//LOG(L_DBG,"new_r_public we are returning error\n");	
	return 0;	
}
Пример #13
0
/*
 * search for P-CSCF contact in usrloc
 * @udomain_t* _d - domain to search in
 * @str* _contact - contact to search for - should be a SIP URI
 * @struct pontact** _c - contact to return to if found (null if not found)
 * @return 0 if found <>0 if not
 */
int get_pcontact(udomain_t* _d, str* _contact, str* _received_host, int received_port, struct pcontact** _c) {
	unsigned int sl, i, aorhash;
	struct pcontact* c;
	ppublic_t* impu;
	struct sip_uri needle_uri, impu_uri;
	int port_match = 0;
	str alias_host = {0, 0};
	struct sip_uri contact_uri;
	
	if (parse_uri(_contact->s, _contact->len, &needle_uri) != 0 ) {
		LM_ERR("failed to parse search URI [%.*s]\n", _contact->len, _contact->s);
		return 1;
	}

	LM_DBG("Searching for contact in P-CSCF usrloc [%.*s]\n",
				_contact->len,
				_contact->s);
	
	/* search in cache */
	aorhash = get_aor_hash(_d, _contact, _received_host, received_port);
	sl = aorhash & (_d->size - 1);
	c = _d->table[sl].first;

	for (i = 0; i < _d->table[sl].n; i++) {

		if ((c->aorhash == aorhash) && (c->aor.len == _contact->len)
				&& !memcmp(c->aor.s, _contact->s, _contact->len)) {
			*_c = c;
			return 0;
		}
		
		if(match_contact_host_port) {
		    LM_DBG("Comparing needle user@host:port [%.*s@%.*s:%d] and contact_user@contact_host:port [%.*s@%.*s:%d]\n", needle_uri.user.len, needle_uri.user.s, 
			    needle_uri.host.len, needle_uri.host.s, needle_uri.port_no,
			    c->contact_user.len, c->contact_user.s, c->contact_host.len, c->contact_host.s, c->contact_port);

		    if((needle_uri.user.len == c->contact_user.len && (memcmp(needle_uri.user.s, c->contact_user.s, needle_uri.user.len) ==0)) &&
			    (needle_uri.host.len == c->contact_host.len && (memcmp(needle_uri.host.s, c->contact_host.s, needle_uri.host.len) ==0)) &&
			    (needle_uri.port_no == c->contact_port)) {
			LM_DBG("Match!!\n");
			*_c = c;
			return 0;
		    }
		}
		
		LM_DBG("Searching for [%.*s] and comparing to [%.*s]\n", _contact->len, _contact->s, c->aor.len, c->aor.s);

		/* hosts HAVE to match */
		if (lookup_check_received && ((needle_uri.host.len != c->received_host.len) || (memcmp(needle_uri.host.s, c->received_host.s, needle_uri.host.len)!=0))) {
			//can't possibly match
			LM_DBG("Lookup failed for [%.*s <=> %.*s]\n", needle_uri.host.len, needle_uri.host.s, c->received_host.len, c->received_host.s);
			c = c->next;
			continue;
		}

		/* one of the ports must match, either the initial registered port, the received port, or one if the security ports (server) */
		if ((needle_uri.port_no != c->contact_port) && (needle_uri.port_no != c->received_port)) {
			//check security ports
			if (c->security) {
				switch (c->security->type) {
				case SECURITY_IPSEC: {
					ipsec_t* ipsec = c->security->data.ipsec;
					if (ipsec) {
						LM_DBG("security server port is %d\n", ipsec->port_us);
						LM_DBG("security client port is %d\n", ipsec->port_uc);
						if (ipsec->port_us == needle_uri.port_no) {
							LM_DBG("security port mathes contact\n");
							port_match = 1;
						}
					}
					break;
				}
				case SECURITY_TLS:
				case SECURITY_NONE:
					LM_WARN("not implemented\n");
					break;
				}
			}
			if (!port_match && c->security_temp) {
				switch (c->security_temp->type) {
				case SECURITY_IPSEC: {
					ipsec_t* ipsec = c->security_temp->data.ipsec;
					if (ipsec) {
						LM_DBG("temp security server port is %d\n", ipsec->port_us);
						LM_DBG("temp security client port is %d\n", ipsec->port_uc);
						if (ipsec->port_us == needle_uri.port_no) {
							LM_DBG("temp security port mathes contact\n");
							port_match = 1;
						}
					}
					break;
				}
				case SECURITY_TLS:
				case SECURITY_NONE:
					LM_WARN("not implemented\n");
					break;
				}
			}
		} else {
			port_match = 1;
		}

		if (!port_match){
			LM_DBG("Port don't match: %d (contact) %d (received) != %d!\n",
		c->contact_port, c->received_port, needle_uri.port_no);
			c = c->next;
			continue;
		}

		/* user parts must match (if not wildcarded) with either primary contact OR with any userpart in the implicit set (associated URIs).. */
		if((needle_uri.user.len == c->contact_user.len) && (memcmp(needle_uri.user.s, c->contact_user.s,needle_uri.user.len) == 0)) {
		    LM_DBG("Needle user part matches contact user part therefore this is a match\n");
		    *_c = c;
		    return 0;
		} else if ((needle_uri.user.len == 1) && (memcmp(needle_uri.user.s, "*", 1) == 0)) { /*wild card*/
		    LM_DBG("This a wild card user part - we must check if hosts match or needle host matches alias\n");
		    if(memcmp(needle_uri.host.s, c->contact_host.s, needle_uri.host.len) == 0) {
			LM_DBG("Needle host matches contact host therefore this is a match\n");
			*_c = c;
			return 0;
		    } else if ((parse_uri(c->aor.s, c->aor.len, &contact_uri) == 0) && ((get_alias_host_from_contact(&contact_uri.params, &alias_host)) == 0) &&
			    (memcmp(needle_uri.host.s, alias_host.s, alias_host.len) == 0)) {
			LM_DBG("Needle host matches contact alias therefore this is a match\n");
			*_c = c;
			return 0;
			
		    }
		}

		/* check impus user parts */
		impu = c->head;
		while (impu) {
			if (parse_uri(impu->public_identity.s, impu->public_identity.len, &impu_uri) != 0) {
				LM_ERR("failed to parse IMPU URI [%.*s]...continuing\n", impu->public_identity.len, impu->public_identity.s);
				impu = impu->next;
				continue;
			}
			LM_DBG("comparing first %d chars of impu [%.*s] for contact userpart [%.*s]\n",
					needle_uri.user.len,
					impu->public_identity.len, impu->public_identity.s,
					needle_uri.user.len, needle_uri.user.s);
			if (needle_uri.user.len == impu_uri.user.len && (memcmp(needle_uri.user.s, impu_uri.user.s, impu_uri.user.len)==0)) {
				*_c = c;
				return 0;
			}
			impu = impu->next;
		}

		c = c->next;
	}
	return 1; /* Nothing found */
}