/** * 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; }
/* 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
/** * 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; }
/** * 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; }
/* 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 */ }
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 */ }
/** * 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; }
/* * 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 */ }