/*! \brief the is_registered() function * Return true if the AOR in the Request-URI is registered, * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ int registered(struct sip_msg* _m, udomain_t* _d, str* _uri) { str uri, aor; urecord_t* r; ucontact_t* ptr; int res; int_str match_callid=(int_str)0; if(_uri!=NULL) { uri = *_uri; } else { if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; } if (extract_aor(&uri, &aor, NULL) < 0) { LM_ERR("failed to extract address of record\n"); return -1; } ul.lock_udomain(_d, &aor); res = ul.get_urecord(_d, &aor, &r); if (res < 0) { ul.unlock_udomain(_d, &aor); LM_ERR("failed to query usrloc\n"); return -1; } if (res == 0) { if (reg_callid_avp_name.n) { struct usr_avp *avp = search_first_avp( reg_callid_avp_type, reg_callid_avp_name, &match_callid, 0); if (!(avp && is_avp_str_val(avp))) match_callid.n = 0; match_callid.s.s = NULL; } else { match_callid.n = 0; match_callid.s.s = NULL; } for (ptr = r->contacts; ptr; ptr = ptr->next) { if(!VALID_CONTACT(ptr, act_time)) continue; if (match_callid.s.s && /* optionally enforce tighter matching w/ Call-ID */ memcmp(match_callid.s.s,ptr->callid.s,match_callid.s.len)) continue; ul.release_urecord(r); ul.unlock_udomain(_d, &aor); LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s)); return 1; } } ul.unlock_udomain(_d, &aor); LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s)); return -1; }
/* * Process REGISTER request and save it's contacts */ static inline int save_real(struct sip_msg* _m, udomain_t* _t, char* _s, int doreply) { contact_t* c; int st; str aor, ua; rerrno = R_FINE; if (parse_message(_m) < 0) { goto error; } if (check_contacts(_m, &st) > 0) { goto error; } get_act_time(); c = get_first_contact(_m); if (extract_aor(&get_to(_m)->uri, &aor) < 0) { LOG(L_ERR, "save(): Error while extracting Address Of Record\n"); goto error; } ua.len = 0; if (parse_headers(_m, HDR_USERAGENT, 0) != -1 && _m->user_agent && _m->user_agent->body.len > 0) { ua.len = _m->user_agent->body.len; ua.s = _m->user_agent->body.s; } if (ua.len == 0) { ua.len = UA_DUMMY_LEN; ua.s = UA_DUMMY_STR; } if (c == 0) { if (st) { if (star(_t, &aor) < 0) goto error; } else { if (no_contacts(_t, &aor) < 0) goto error; } } else { if (contacts(_m, c, _t, &aor, &ua) < 0) goto error; } if (doreply && (send_reply(_m) < 0)) return -1; else return 1; error: if (doreply) send_reply(_m); return 0; }
/** * Check that the IMPU at the Term S has at least one valid contact... * @param _m - msg * @param _t - t * @param _s - s * @return true if there is at least one valid contact. false if not */ int term_impu_has_contact(struct sip_msg* _m, udomain_t* _d, char* _s) { impurecord_t* r; str aor, uri; ucontact_t* ptr; int res; int ret; int i = 0; if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; if (extract_aor(&uri, &aor) < 0) { LM_ERR("failed to extract address of record\n"); return -3; } get_act_time(); ul.lock_udomain(_d, &aor); res = ul.get_impurecord(_d, &aor, &r); if (res != 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain(_d, &aor); return -1; } while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) { if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s); i++; ret = 1; break; } i++; } /* look first for an un-expired and supported contact */ if (ptr == 0) { /* nothing found */ ret = -1; } ul.unlock_udomain(_d, &aor); return ret; }
/* * Return true if the AOR in the Request-URI is registered, * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ int registered(struct sip_msg* _m, char* _t, char* _s) { str uri, aor; urecord_t* r; ucontact_t* ptr; int res; if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; if (extract_aor(&uri, &aor) < 0) { LOG(L_ERR, "registered(): Error while extracting address of record\n"); return -1; } ul.lock_udomain((udomain_t*)_t); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res < 0) { ul.unlock_udomain((udomain_t*)_t); LOG(L_ERR, "registered(): Error while querying usrloc\n"); return -1; } if (res == 0) { ptr = r->contacts; while (ptr && !VALID_CONTACT(ptr, act_time)) { ptr = ptr->next; } if (ptr) { ul.unlock_udomain((udomain_t*)_t); DBG("registered(): '%.*s' found in usrloc\n", aor.len, ZSW(aor.s)); return 1; } } ul.unlock_udomain((udomain_t*)_t); DBG("registered(): '%.*s' not found in usrloc\n", aor.len, ZSW(aor.s)); return -1; }
int unregister(struct sip_msg* _m, udomain_t* _d, str* _uri) { str aor = {0, 0}; sip_uri_t *u; u = parse_to_uri(_m); if(u==NULL) return -2; if (extract_aor(_uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } if (star(_m, _d, &aor, &u->host) < 0) { LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s); return -1; } return 1; }
/*! \brief the is_registered() function * Return true if the AOR in the Request-URI is registered, * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ int registered(struct sip_msg* _m, char* _t, char* _s, char *_c) { str uri, aor; urecord_t* r; ucontact_t* ptr; pv_value_t val; str callid; int res; /* get the AOR */ if (_s) { if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) { LM_ERR("failed to getAOR PV value\n"); return -1; } if ( (val.flags&PV_VAL_STR)==0 ) { LM_ERR("AOR PV vals is not string\n"); return -1; } uri = val.rs; } else { if (_m->first_line.type!=SIP_REQUEST) { LM_ERR("no AOR and called for a reply!"); return -1; } if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; } if (extract_aor(&uri, &aor,0,0) < 0) { LM_ERR("failed to extract address of record\n"); return -1; } /* get the callid */ if (_c) { if (pv_get_spec_value( _m, (pv_spec_p)_c, &val)!=0) { LM_ERR("failed to get callid PV value\n"); return -1; } if ( (val.flags&PV_VAL_STR)==0 ) { LM_ERR("callid PV vals is not string\n"); return -1; } callid = val.rs; } else { callid.s = NULL; callid.len = 0; } ul.lock_udomain((udomain_t*)_t, &aor); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res < 0) { ul.unlock_udomain((udomain_t*)_t, &aor); LM_ERR("failed to query usrloc\n"); return -1; } if (res == 0) { ptr = r->contacts; while (ptr && !VALID_CONTACT(ptr, act_time)) { ptr = ptr->next; } for( ; ptr ; ptr=ptr->next ) { if (callid.len==0 || (callid.len==ptr->callid.len && memcmp(callid.s,ptr->callid.s,callid.len)==0 ) ) { ul.unlock_udomain((udomain_t*)_t, &aor); LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s)); return 1; } } } ul.unlock_udomain((udomain_t*)_t, &aor); LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s)); return -1; }
/* * Lookup contact in the database and rewrite Request-URI */ int lookup(struct sip_msg* _m, char* _t, char* _s) { urecord_t* r; str aor, uri; ucontact_t* ptr; int res; int bflags; if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; if (extract_aor(&uri, &aor) < 0) { LOG(L_ERR, "lookup(): Error while extracting address of record\n"); return -1; } get_act_time(); ul.lock_udomain((udomain_t*)_t); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res < 0) { LOG(L_ERR, "lookup(): Error while querying usrloc\n"); ul.unlock_udomain((udomain_t*)_t); return -2; } if (res > 0) { DBG("lookup(): '%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain((udomain_t*)_t); return -3; } ptr = r->contacts; while ((ptr) && !VALID_CONTACT(ptr, act_time)) ptr = ptr->next; if (ptr) { if (rewrite_uri(_m, &ptr->c) < 0) { LOG(L_ERR, "lookup(): Unable to rewrite Request-URI\n"); ul.unlock_udomain((udomain_t*)_t); return -4; } if (ptr->received.s && ptr->received.len) { if (set_dst_uri(_m, &ptr->received) < 0) { ul.unlock_udomain((udomain_t*)_t); return -4; } } set_ruri_q(ptr->q); /* for RURI branch, the nat flag goes into msg */ if ( ptr->flags&FL_NAT ) _m->flags |= nat_flag; if (ptr->sock) _m->force_send_socket = ptr->sock; ptr = ptr->next; } else { /* All contacts expired */ ul.unlock_udomain((udomain_t*)_t); return -5; } /* Append branches if enabled */ if (!append_branches) goto skip; for( ; ptr ; ptr = ptr->next ) { if (VALID_CONTACT(ptr, act_time)) { /* for additional branches, the nat flag goes into dset */ bflags = (use_branch_flags && (ptr->flags & FL_NAT))?nat_flag:0; if (append_branch(_m, &ptr->c, &ptr->received, ptr->q, bflags, ptr->sock) == -1) { LOG(L_ERR, "lookup(): Error while appending a branch\n"); /* Return 1 here so the function succeeds even if * appending of a branch failed */ /* Also give a chance to the next branches*/ continue; } if (!use_branch_flags && (ptr->flags & FL_NAT)) _m->flags |= nat_flag; } } skip: ul.unlock_udomain((udomain_t*)_t); return 1; }
int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri) { contact_t* c; int st, mode; str aor; int ret; sip_uri_t *u; rr_t *route; struct sip_uri puri; param_hooks_t hooks; param_t *params; contact_t *contact; int use_ob = 1, use_regid = 1; u = parse_to_uri(_m); if(u==NULL) goto error; rerrno = R_FINE; ret = 1; if (parse_message(_m) < 0) { goto error; } if (check_contacts(_m, &st) > 0) { goto error; } if (parse_supported(_m) == 0) { if (!(get_supported(_m) & F_OPTION_TAG_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_REQUIRE) { LM_WARN("Outbound required by server and not supported by UAC\n"); rerrno = R_OB_UNSUP; goto error; } } if (parse_require(_m) == 0) { if ((get_require(_m) & F_OPTION_TAG_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_NONE) { LM_WARN("Outbound required by UAC and not supported by server\n"); rerrno = R_OB_REQD; goto error; } } if (reg_outbound_mode != REG_OUTBOUND_NONE && _m->contact && _m->contact->parsed && !(parse_headers(_m, HDR_VIA2_F, 0) == -1 || _m->via2 == 0 || _m->via2->error != PARSE_OK)) { /* Outbound supported on server, and more than one Via: - not the first hop */ if (!(parse_headers(_m, HDR_PATH_F, 0) == -1 || _m->path == 0)) { route = (rr_t *)0; if (parse_rr_body(_m->path->body.s, _m->path->body.len, &route) < 0) { LM_ERR("Failed to parse Path: header body\n"); goto error; } if (parse_uri(route->nameaddr.uri.s, route->nameaddr.uri.len, &puri) < 0) { LM_ERR("Failed to parse Path: URI\n"); goto error; } if (parse_params(&puri.params, CLASS_URI, &hooks, ¶ms) != 0) { LM_ERR("Failed to parse Path: URI parameters\n"); goto error; } if (!hooks.uri.ob) { /* No ;ob parameter to top Path: URI - no outbound */ use_ob = 0; } } else { /* No Path: header - no outbound */ use_ob = 0; } contact = ((contact_body_t *) _m->contact->parsed)->contacts; if (!contact) { LM_ERR("empty Contact:\n"); goto error; } if ((use_ob == 0) && (reg_regid_mode == REG_REGID_OUTBOUND)) { if ((get_supported(_m) & F_OPTION_TAG_OUTBOUND) && contact->reg_id) { LM_WARN("Outbound used by UAC but not supported by edge proxy\n"); rerrno = R_OB_UNSUP_EDGE; goto error; } else { /* ignore ;reg-id parameter */ use_regid = 0; } } } get_act_time(); c = get_first_contact(_m); if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); goto error; } mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE; if (c == 0) { if (st) { if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error; else ret=3; } else { if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error; else ret=4; } } else { mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0; if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode, use_regid)) < 0) goto error; ret = (ret==0)?1:ret; } update_stat(accepted_registrations, 1); /* Only send reply upon request, not upon reply */ if ((is_route_type(REQUEST_ROUTE) || is_route_type(FAILURE_ROUTE)) && !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0)) return -1; return ret; error: update_stat(rejected_registrations, 1); if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) ) reg_send_reply(_m); return 0; }
int unregister(struct sip_msg* _m, udomain_t* _d, str* _uri, str *_ruid) { str aor = {0, 0}; sip_uri_t *u; urecord_t *r; ucontact_t *c; int res; if (_ruid == NULL) { /* No ruid provided - remove all contacts for aor */ if (extract_aor(_uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } u = parse_to_uri(_m); if(u==NULL) return -2; if (star(_m, _d, &aor, &u->host) < 0) { LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s); return -1; } } else { /* ruid provided - remove a specific contact */ if (_uri->len > 0) { if (extract_aor(_uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } if (ul.get_urecord_by_ruid(_d, ul.get_aorhash(&aor), _ruid, &r, &c) != 0) { LM_WARN("AOR/Contact not found\n"); return -1; } if (ul.delete_ucontact(r, c) != 0) { ul.unlock_udomain(_d, &aor); LM_WARN("could not delete contact\n"); return -1; } ul.unlock_udomain(_d, &aor); } else { res = ul.delete_urecord_by_ruid(_d, _ruid); switch (res) { case -1: LM_ERR("could not delete contact\n"); return -1; case -2: LM_WARN("contact not found\n"); return -1; default: return 1; } } } return 1; }
int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri) { contact_t* c; int st, mode; str aor; int ret; sip_uri_t *u; u = parse_to_uri(_m); if(u==NULL) goto error; rerrno = R_FINE; ret = 1; if (parse_message(_m) < 0) { goto error; } if (check_contacts(_m, &st) > 0) { goto error; } if (parse_supported(_m) == 0) { if (!(((struct supported_body *)_m->supported->parsed)->supported_all & F_SUPPORTED_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_REQUIRE) { LM_WARN("Outbound required by server and not supported by UAC\n"); rerrno = R_OB_UNSUP; goto error; } } get_act_time(); c = get_first_contact(_m); if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); goto error; } mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE; if (c == 0) { if (st) { if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error; else ret=3; } else { if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error; else ret=4; } } else { mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0; if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode)) < 0) goto error; ret = (ret==0)?1:ret; } update_stat(accepted_registrations, 1); /* Only send reply upon request, not upon reply */ if ((is_route_type(REQUEST_ROUTE)) && !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0)) return -1; return ret; error: update_stat(rejected_registrations, 1); if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) ) reg_send_reply(_m); return 0; }
int is_other_contact_f(struct sip_msg* msg, char* _d, char *_s) { pv_spec_p spec = (pv_spec_p)_s; struct usr_avp *avp = NULL; urecord_t *r = NULL; str ip, contact; str uri, aor; ucontact_t *c; contact_t* ct; int exp, found; udomain_t* ud = (udomain_t*)_d; if (parse_message(msg) < 0) { LM_ERR("unable to parse message\n"); return -2; } if (!ud) { LM_ERR("no location specified\n"); return -2; } /* msg doesn't have contacts */ if (!msg->contact || !(ct = (((contact_body_t*)msg->contact->parsed)->contacts))) return -1; while (ct) { /* if expires is 0 */ calc_contact_expires(msg, ct->expires, &exp); if (exp) break; ct = ct->next; } if (!ct) { LM_DBG("contact has expire 0\n"); return -1; } uri = get_to(msg)->uri; if (extract_aor(&uri, &aor) < 0) { LM_ERR("failed to extract AOR record\n"); return -2; } ul.lock_udomain(ud, &aor); ul.get_urecord(ud, &aor, &r); if (!r) { /* dont't test anything */ LM_DBG("no contact found for aor=<%.*s>\n", aor.len, aor.s); found = -1; goto end; } else { c = r->contacts; } while (c) { if (!c->received.len || !c->received.s || c->received.len < 4 /* sip:*/) { c = c->next; continue; } contact.s = c->received.s + 4; /* check for "sips:" */ if (*contact.s == ':') { contact.len = c->received.len - 5; contact.s++; } else { /* skip "sip:" */ contact.len = c->received.len - 4; } avp = NULL; found = 0; /* the ip should always be a string */ while ((avp = search_first_avp(spec->pvp.pvn.u.isname.type, spec->pvp.pvn.u.isname.name.n, (int_str *)&ip, avp))!=0) { if (!(avp->flags & AVP_VAL_STR)) { LM_NOTICE("avp value should be string\n"); continue; } if ((contact.len == ip.len || (contact.len>ip.len && contact.s[ip.len]==':')) && !memcmp(contact.s, ip.s, ip.len)) { found = 1; break; } } if (!found) { LM_DBG("no contact <%.*s> registered earlier\n", contact.len, contact.s); found = 1; goto end; } c = c->next; } found = -1; end: ul.unlock_udomain(ud, &aor); return found; }
/*! \brief * Lookup contact in the database and rewrite Request-URI * \return: -1 : not found * -2 : found but method not allowed * -3 : error */ int lookup(struct sip_msg* _m, udomain_t* _d) { impurecord_t* r; str aor, uri; ucontact_t* ptr; int res; int ret; str path_dst; flag_t old_bflags; int i = 0; if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; if (extract_aor(&uri, &aor) < 0) { LM_ERR("failed to extract address of record\n"); return -3; } get_act_time(); ul.lock_udomain(_d, &aor); res = ul.get_impurecord(_d, &aor, &r); if (res > 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain(_d, &aor); return -1; } ret = -1; while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) { if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s); i++; break; } i++; } /* look first for an un-expired and suported contact */ if (ptr == 0) { /* nothing found */ goto done; } ret = 1; if (ptr) { if (rewrite_uri(_m, &ptr->c) < 0) { LM_ERR("unable to rewrite Request-URI\n"); ret = -3; goto done; } /* reset next hop address */ reset_dst_uri(_m); /* If a Path is present, use first path-uri in favour of * received-uri because in that case the last hop towards the uac * has to handle NAT. - agranig */ if (ptr->path.s && ptr->path.len) { if (get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); ret = -3; goto done; } if (set_path_vector(_m, &ptr->path) < 0) { LM_ERR("failed to set path vector\n"); ret = -3; goto done; } if (set_dst_uri(_m, &path_dst) < 0) { LM_ERR("failed to set dst_uri of Path\n"); ret = -3; goto done; } } else if (ptr->received.s && ptr->received.len) { if (set_dst_uri(_m, &ptr->received) < 0) { ret = -3; goto done; } } set_ruri_q(ptr->q); old_bflags = 0; getbflagsval(0, &old_bflags); setbflagsval(0, old_bflags | ptr->cflags); if (ptr->sock) set_force_socket(_m, ptr->sock); ptr = ptr->next; } /* Append branches if enabled */ if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done; //the last i was the first valid contact we found - let's go through the rest of valid contacts and append the branches. while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) { if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { path_dst.len = 0; if (ptr->path.s && ptr->path.len && get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); continue; } /* The same as for the first contact applies for branches * regarding path vs. received. */ if (km_append_branch(_m, &ptr->c, path_dst.len ? &path_dst : &ptr->received, &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) { LM_ERR("failed to append a branch\n"); /* Also give a chance to the next branches*/ continue; } } i++; } done: ul.unlock_udomain(_d, &aor); return ret; }
/** * _remove - Delete an entire AOR entry or just one or more of its Contacts * Parameter format: _remove(domain, AOR[, Contact URI or plain hostname]) * * @udomain: (udomain_t *) * @aor_gp: address-of-record as a SIP URI (plain string or pvar) * @contact_gp: contact to be deleted or domain in front of multiple contacts * * @return: 1 on success, negative on failure */ int _remove(struct sip_msg *msg, char *udomain, char *aor_gp, char *contact_gp) { struct sip_uri puri; struct hostent delete_he, *he; urecord_t *record; ucontact_t *contact, *it; str uri, aor_user, delete_user = { NULL, 0 }; int err, count = 0; int delete_by_hostname = 0; unsigned short delete_port; memset(&delete_he, 0, sizeof delete_he); if (fixup_get_svalue(msg, (gparam_p)aor_gp, &uri) != 0) { LM_ERR("failed to get gparam_t value\n"); return E_UNSPEC; } if (extract_aor( &uri, &aor_user,0,0) < 0) { LM_ERR("failed to extract Address Of Record\n"); return E_BAD_URI; } ul.lock_udomain((udomain_t *)udomain, &aor_user); if (ul.get_urecord((udomain_t *)udomain, &aor_user, &record) != 0) { LM_DBG("no record '%.*s' found!\n", aor_user.len, aor_user.s); err = 1; goto out_unlock; } /* if no contact uri param is given, delete the whole urecord entry */ if (!contact_gp) { if (ul.delete_urecord((udomain_t *)udomain, &aor_user, record, 0) != 0) { LM_ERR("failed to delete urecord for aor '%.*s'\n", aor_user.len, aor_user.s); err = E_UNSPEC; goto out_unlock; } err = 1; goto out_unlock; } if (fixup_get_svalue(msg, (gparam_p)contact_gp, &uri) != 0) { LM_ERR("failed to retrieve value of contact pv\n"); err = E_UNSPEC; goto out_unlock; } /* minimum two-letters for the domain name */ if (uri.len < 5) { LM_ERR("Invalid domain given: '%.*s'\n", uri.len, uri.s); err = E_INVALID_PARAMS; goto out_unlock; } /* a domain/IP address was given instead of a SIP contact URI */ if (uri.s[0] != 's' || uri.s[1] != 'i' || uri.s[2] != 'p' || (uri.s[3] != ':' && (uri.s[3] != 's' || uri.s[4] != ':'))) { delete_by_hostname = 1; he = sip_resolvehost(&uri, &delete_port, NULL, 0, NULL); if (!he) { LM_ERR("cannot resolve given host: '%.*s'\n", uri.len, uri.s); err = E_UNSPEC; goto out_unlock; } LM_DBG("Delete by host: '%s'\n", inet_ntoa(*(struct in_addr *)(he->h_addr_list[0]))); } else { LM_DBG("parsing uri: %.*s\n", uri.len, uri.s); if (parse_uri(uri.s, uri.len, &puri) != 0) { LM_ERR("failed to parse contact uri: '%.*s'\n", uri.len, uri.s); err = E_BAD_URI; goto out_unlock; } delete_user = puri.user; he = sip_resolvehost(&puri.host, &delete_port, &puri.proto, 0, NULL); if (!he) { LM_ERR("cannot resolve given uri: '%.*s'\n", uri.len, uri.s); err = E_UNSPEC; goto out_unlock; } if (puri.port_no > 0) delete_port = puri.port_no; LM_DBG("Delete by contact: [ User %.*s | Host %s | Port %d ]\n", delete_user.len, delete_user.s, inet_ntoa(*(struct in_addr *)(he->h_addr_list[0])), delete_port); } if (hostent_cpy(&delete_he, he) != 0) { LM_ERR("no more pkg mem\n"); err = E_OUT_OF_MEM; goto out_unlock; } for (it = record->contacts; it; ) { contact = it; it = it->next; count++; LM_DBG("parsing contact uri '%.*s'\n", contact->c.len, contact->c.s); if (parse_uri(contact->c.s, contact->c.len, &puri) != 0) { LM_ERR("failed to parse contact uri: '%.*s'\n", contact->c.len, contact->c.s); err = E_BAD_URI; goto out_unlock; } /* if necessary, solve the next_hop towards the contact */ he = sip_resolvehost(&contact->next_hop.name, &contact->next_hop.port, &contact->next_hop.proto, 0, NULL); if (!he) { LM_ERR("failed to resolve next hop of contact '%.*s'\n", contact->c.len, contact->c.s); continue; } LM_DBG("Contact: [ User %.*s | Host %s | Port %d ]\n", puri.user.len, puri.user.s, inet_ntoa(*(struct in_addr *)(he->h_addr_list[0])), puri.port_no); if (delete_by_hostname) { if (!memcmp(delete_he.h_addr_list[0], he->h_addr_list[0], he->h_length)) { ul.delete_ucontact(record, contact, 0); count--; } } else { if (delete_user.len == puri.user.len && delete_port == puri.port_no && !memcmp(delete_he.h_addr_list[0], he->h_addr_list[0], he->h_length) && !memcmp(delete_user.s, puri.user.s, puri.user.len)) { ul.delete_ucontact(record, contact, 0); count--; } } } err = 1; /* remove the AOR if no more contacts are attached */ if (count == 0) { if (ul.delete_urecord((udomain_t *)udomain, &aor_user, record, 0) != 0) { LM_ERR("failed to delete urecord for aor '%.*s'\n", aor_user.len, aor_user.s); err = 1; } } out_unlock: ul.unlock_udomain((udomain_t *)udomain, &aor_user); free_hostent(&delete_he); return err; }
int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, int match_action_flag) { str uri, aor; urecord_t* r; ucontact_t* ptr; int res; str match_callid = {0,0}; str match_received = {0,0}; str match_contact = {0,0}; sr_xavp_t *vavp = NULL; if(_uri!=NULL) { uri = *_uri; } else { if(IS_SIP_REPLY(_m)) { if (parse_to_header(_m) < 0) { LM_ERR("failed to prepare the message\n"); return -1; } uri = get_to(_m)->uri; } else { if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; } } if (extract_aor(&uri, &aor, NULL) < 0) { LM_ERR("failed to extract address of record\n"); return -1; } ul.lock_udomain(_d, &aor); res = ul.get_urecord(_d, &aor, &r); if (res < 0) { ul.unlock_udomain(_d, &aor); LM_ERR("failed to query usrloc\n"); return -1; } if (res == 0) { LM_DBG("searching with match flags (%d,%d)\n", match_flag, match_action_flag); if(reg_xavp_cfg.s!=NULL) { if((match_flag & 1) && (vavp = xavp_get_child_with_sval(®_xavp_cfg, &match_callid_name)) != NULL && vavp->val.v.s.len > 0) { match_callid = vavp->val.v.s; LM_DBG("matching with callid %.*s\n", match_callid.len, match_callid.s); } if((match_flag & 2) && (vavp = xavp_get_child_with_sval(®_xavp_cfg, &match_received_name)) != NULL && vavp->val.v.s.len > 0) { match_received = vavp->val.v.s; LM_DBG("matching with received %.*s\n", match_received.len, match_received.s); } if((match_flag & 4) && (vavp = xavp_get_child_with_sval(®_xavp_cfg, &match_contact_name)) != NULL && vavp->val.v.s.len > 0) { match_contact = vavp->val.v.s; LM_DBG("matching with contact %.*s\n", match_contact.len, match_contact.s); } } for (ptr = r->contacts; ptr; ptr = ptr->next) { if(!VALID_CONTACT(ptr, act_time)) continue; if (match_callid.s && /* optionally enforce tighter matching w/ Call-ID */ match_callid.len > 0 && (match_callid.len != ptr->callid.len || memcmp(match_callid.s, ptr->callid.s, match_callid.len))) continue; if (match_received.s && /* optionally enforce tighter matching w/ ip:port */ match_received.len > 0 && (match_received.len != ptr->received.len || memcmp(match_received.s, ptr->received.s, match_received.len))) continue; if (match_contact.s && /* optionally enforce tighter matching w/ Contact */ match_contact.len > 0 && (match_contact.len != ptr->c.len || memcmp(match_contact.s, ptr->c.s, match_contact.len))) continue; if(!(match_action_flag & 2)) { xavp_rcd_helper(ptr); } if((ptr->xavp!=NULL) && (match_action_flag & 1)) { sr_xavp_t *xavp = xavp_clone_level_nodata(ptr->xavp); if(xavp_add(xavp, NULL)<0) { LM_ERR("error adding xavp for %.*s after successful match\n", aor.len, ZSW(aor.s)); xavp_destroy_list(&xavp); } } ul.release_urecord(r); ul.unlock_udomain(_d, &aor); LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s)); return 1; } } ul.unlock_udomain(_d, &aor); LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s)); return -1; }
/** * _remove - Delete an entire AOR entry or one or more of its Contacts * * @domain: logical domain name (usually name of location table) * @aor_gp: address-of-record as a SIP URI (plain string or pvar) * @contact_gp: contact URI to be deleted * @next_hop_gp: IP/domain in front of contacts to be deleted * @sip_instance_gp: delete contacts with given "+sip_instance" * * @return: 1 on success, negative on failure */ int _remove(struct sip_msg *msg, void *udomain, str *aor_uri, str *match_ct, str *match_next_hop, str *match_sin) { struct hostent delete_nh_he, *he; urecord_t *record; ucontact_t *contact, *it; str aor_user; int ret = 1; unsigned short delete_port = 0; if (extract_aor(aor_uri, &aor_user, 0, 0) < 0) { LM_ERR("failed to extract Address Of Record\n"); return E_BAD_URI; } ul.lock_udomain((udomain_t *)udomain, &aor_user); if (ul.get_urecord((udomain_t *)udomain, &aor_user, &record) != 0) { LM_DBG("no record '%.*s' found!\n", aor_user.len, aor_user.s); goto out_unlock; } /* without any additional filtering, delete the whole urecord entry */ if (!match_ct && !match_next_hop && !match_sin) { if (ul.delete_urecord((udomain_t *)udomain, &aor_user, record, 0) != 0) { LM_ERR("failed to delete urecord for aor '%.*s'\n", aor_user.len, aor_user.s); ret = E_UNSPEC; goto out_unlock; } goto out_unlock; } if (match_ct && match_ct->s) LM_DBG("Delete by contact: [%.*s]\n", match_ct->len, match_ct->s); if (match_sin && match_sin->s) LM_DBG("Delete by sip_instance: [%.*s]\n", match_sin->len, match_sin->s); if (match_next_hop->s) { he = sip_resolvehost(match_next_hop, &delete_port, NULL, 0, NULL); if (!he) { LM_ERR("cannot resolve given host: '%.*s'\n", match_next_hop->len, match_next_hop->s); ret = E_UNSPEC; goto out_unlock; } LM_DBG("Delete by host: '%s'\n", inet_ntoa(*(struct in_addr *)(he->h_addr_list[0]))); if (hostent_cpy(&delete_nh_he, he) != 0) { LM_ERR("no more pkg mem\n"); ret = E_OUT_OF_MEM; goto out_unlock; } } for (it = record->contacts; it; ) { contact = it; it = it->next; LM_DBG("checking contact uri '%.*s'\n", contact->c.len, contact->c.s); he = sip_resolvehost(&contact->next_hop.name, &contact->next_hop.port, &contact->next_hop.proto, 0, NULL); if (!he) { LM_ERR("failed to resolve next hop %.*s of contact '%.*s'\n", contact->next_hop.name.len, contact->next_hop.name.s, contact->c.len, contact->c.s); continue; } LM_DBG("next hop is [%.*s] resolving to [%s]\n", contact->next_hop.name.len, contact->next_hop.name.s, inet_ntoa(*(struct in_addr *)(he->h_addr_list[0]))); if (match_next_hop->s) { if (memcmp(delete_nh_he.h_addr_list[0], he->h_addr_list[0], he->h_length)) continue; } if (match_ct->s) { if (match_ct->len != contact->c.len || memcmp(match_ct->s, contact->c.s, match_ct->len)) continue; } if (match_sin->s) { if (str_strcmp(match_sin, &contact->instance)) continue; } ul.delete_ucontact(record, contact, 0); } ul.release_urecord(record, 0); out_unlock: ul.unlock_udomain((udomain_t *)udomain, &aor_user); if (match_next_hop->s) free_hostent(&delete_nh_he); return ret; }
int save_aux(struct sip_msg* _m, str* forced_binding, void* _d, str* flags_s, str* uri, str* _owtag) { struct save_ctx sctx; contact_t* c; contact_t* forced_c = NULL; int st; rerrno = R_FINE; memset( &sctx, 0 , sizeof(sctx)); sctx.max_contacts = -1; sctx.flags = 0; sctx.min_expires = min_expires; sctx.max_expires = max_expires; if ( flags_s ) { for( st=0 ; st< flags_s->len ; st++ ) { switch (flags_s->s[st]) { case 'm': sctx.flags |= REG_SAVE_MEMORY_FLAG; break; case 'r': sctx.flags |= REG_SAVE_NOREPLY_FLAG; break; case 's': sctx.flags |= REG_SAVE_SOCKET_FLAG; break; case 'v': sctx.flags |= REG_SAVE_PATH_RECEIVED_FLAG; break; case 'f': sctx.flags |= REG_SAVE_FORCE_REG_FLAG; break; case 'c': sctx.max_contacts = 0; while (st<flags_s->len-1 && isdigit(flags_s->s[st+1])) { sctx.max_contacts = sctx.max_contacts*10 + flags_s->s[st+1] - '0'; st++; } break; case 'e': sctx.min_expires = 0; while (st<flags_s->len-1 && isdigit(flags_s->s[st+1])) { sctx.min_expires = sctx.min_expires*10 + flags_s->s[st+1] - '0'; st++; } break; case 'E': sctx.max_expires = 0; while (st<flags_s->len-1 && isdigit(flags_s->s[st+1])) { sctx.max_expires = sctx.max_expires*10 + flags_s->s[st+1] - '0'; st++; } break; case 'p': if (st<flags_s->len-1) { st++; if (flags_s->s[st]=='2') { sctx.flags |= REG_SAVE_PATH_STRICT_FLAG; break; } if (flags_s->s[st]=='1') { sctx.flags |= REG_SAVE_PATH_LAZY_FLAG; break; } if (flags_s->s[st]=='0') { sctx.flags |= REG_SAVE_PATH_OFF_FLAG; break; } } default: LM_WARN("unsupported flag %c \n",flags_s->s[st]); } } } if(route_type == ONREPLY_ROUTE) sctx.flags |= REG_SAVE_NOREPLY_FLAG; /* if no max_contact per AOR is defined, use the global one */ if (sctx.max_contacts == -1) sctx.max_contacts = max_contacts; if (parse_reg_headers(_m) < 0) { goto error; } if (forced_binding) { if (parse_contacts(forced_binding, &forced_c) < 0) { LM_ERR("Unable to parse forced binding [%.*s]\n", forced_binding->len, forced_binding->s); goto error; } /* prevent processing all the headers from the message */ reset_first_contact(); st = 0; c = forced_c; } else { if (check_contacts(_m, &st) > 0) { goto error; } c = get_first_contact(_m); } update_act_time(); if (!uri) uri = &(get_to(_m)->uri); if (_owtag) sctx.ownership_tag = *_owtag; if (extract_aor(uri, &sctx.aor,0,0) < 0) { LM_ERR("failed to extract Address Of Record\n"); goto error; } if (c == 0) { if (st) { if (star((udomain_t*)_d, &sctx,_m) < 0) goto error; } else { if (no_contacts((udomain_t*)_d, &sctx.aor,_m) < 0) goto error; } } else { if (add_contacts(_m, c, (udomain_t*)_d, &sctx) < 0) goto error; } update_stat(accepted_registrations, 1); if (!is_cflag_set(REG_SAVE_NOREPLY_FLAG) && (send_reply(_m,sctx.flags)<0)) goto return_minus_one; if (forced_c) free_contacts(&forced_c); return 1; error: update_stat(rejected_registrations, 1); if ( !is_cflag_set(REG_SAVE_NOREPLY_FLAG) ) send_reply(_m,sctx.flags); if (forced_c) free_contacts(&forced_c); return -2; return_minus_one: if (forced_c) free_contacts(&forced_c); return -1; }
int pv_fetch_contacts_helper(sip_msg_t* msg, udomain_t* dt, str* uri, str* profile) { urecord_t* r; ucontact_t* ptr; ucontact_t* ptr0; ucontact_t* c0; regpv_profile_t *rpp; str aor = {0, 0}; int res; int olen; int ilen; int n; char *p; rpp = regpv_get_profile((str*)profile); if(rpp==0) { LM_ERR("invalid parameters\n"); return -1; } /* check and free if profile already set */ if(rpp->flags) regpv_free_profile(rpp); if (extract_aor(uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } /* copy aor and ul domain */ rpp->aor.s = (char*)pkg_malloc(aor.len*sizeof(char)); if(rpp->aor.s==NULL) { LM_ERR("no more pkg\n"); return -1; } memcpy(rpp->aor.s, aor.s, aor.len); rpp->aor.len = aor.len; rpp->domain = *((udomain_head_t*)dt)->name; rpp->flags = 1; /* copy contacts */ ilen = sizeof(ucontact_t); ul.lock_udomain(dt, &aor); res = ul.get_urecord(dt, &aor, &r); if (res > 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain(dt, &aor); return -1; } ptr = r->contacts; ptr0 = NULL; n = 0; while(ptr) { olen = (ptr->c.len + ptr->received.len + ptr->path.len + ptr->callid.len + ptr->user_agent.len + ptr->ruid.len + ptr->instance.len)*sizeof(char) + ilen; c0 = (ucontact_t*)pkg_malloc(olen); if(c0==NULL) { LM_ERR("no more pkg\n"); ul.release_urecord(r); ul.unlock_udomain(dt, &aor); goto error; } memcpy(c0, ptr, ilen); c0->domain = NULL; c0->aor = NULL; c0->next = NULL; c0->prev = NULL; c0->c.s = (char*)c0 + ilen; memcpy(c0->c.s, ptr->c.s, ptr->c.len); c0->c.len = ptr->c.len; p = c0->c.s + c0->c.len; if(ptr->received.s!=NULL) { c0->received.s = p; memcpy(c0->received.s, ptr->received.s, ptr->received.len); c0->received.len = ptr->received.len; p += c0->received.len; } if(ptr->path.s!=NULL) { c0->path.s = p; memcpy(c0->path.s, ptr->path.s, ptr->path.len); c0->path.len = ptr->path.len; p += c0->path.len; } c0->callid.s = p; memcpy(c0->callid.s, ptr->callid.s, ptr->callid.len); c0->callid.len = ptr->callid.len; p += c0->callid.len; if(ptr->user_agent.s!=NULL) { c0->user_agent.s = p; memcpy(c0->user_agent.s, ptr->user_agent.s, ptr->user_agent.len); c0->user_agent.len = ptr->user_agent.len; p += c0->user_agent.len; } if(ptr->ruid.s!=NULL) { c0->ruid.s = p; memcpy(c0->ruid.s, ptr->ruid.s, ptr->ruid.len); c0->ruid.len = ptr->ruid.len; p += c0->ruid.len; } if(ptr->instance.s!=NULL) { c0->instance.s = p; memcpy(c0->instance.s, ptr->instance.s, ptr->instance.len); c0->instance.len = ptr->instance.len; p += c0->instance.len; } LM_DBG("memory block between %p - %p\n", c0, p); if ((ptr->sock) && (ptr->sock->proto == PROTO_TCP || ptr->sock->proto == PROTO_TLS || ptr->sock->proto == PROTO_WS || ptr->sock->proto == PROTO_WSS)) { c0->tcpconn_id = ptr->tcpconn_id; } if(ptr0==NULL) { rpp->contacts = c0; } else { ptr0->next = c0; c0->prev = ptr0; } n++; ptr0 = c0; ptr = ptr->next; } ul.release_urecord(r); ul.unlock_udomain(dt, &aor); rpp->nrc = n; LM_DBG("fetched <%d> contacts for <%.*s> in [%.*s]\n", n, aor.len, aor.s, rpp->pname.len, rpp->pname.s); return 1; error: regpv_free_profile(rpp); return -1; }
int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri, char* profile) { impurecord_t* r; ucontact_t* ptr; ucontact_t* ptr0; ucontact_t* c0; regpv_profile_t *rpp; str aor = {0, 0}; str u = {0, 0}; int res; int olen; int ilen; int n; char *p; rpp = regpv_get_profile((str*)profile); if(rpp==0) { LM_ERR("invalid parameters\n"); return -1; } /* check and free if profile already set */ if(rpp->flags) regpv_free_profile(rpp); if(fixup_get_svalue(msg, (gparam_p)uri, &u)!=0 || u.len<=0) { LM_ERR("invalid uri parameter\n"); return -1; } if (extract_aor(&u, &aor) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } /* copy aor and ul domain */ rpp->aor.s = (char*)pkg_malloc(aor.len*sizeof(char)); if(rpp->aor.s==NULL) { LM_ERR("no more pkg\n"); return -1; } memcpy(rpp->aor.s, aor.s, aor.len); rpp->aor.len = aor.len; rpp->domain = *((udomain_head_t*)table)->name; rpp->flags = 1; /* copy contacts */ ilen = sizeof(ucontact_t); ul.lock_udomain((udomain_t*)table, &aor); res = ul.get_impurecord((udomain_t*)table, &aor, &r); if (res != 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain((udomain_t*)table, &aor); return -1; } ptr = 0;//r->contacts;TODO ptr0 = NULL; n = 0; while(ptr) { olen = (ptr->c.len + ptr->received.len + ptr->path.len + ptr->callid.len + ptr->user_agent.len)*sizeof(char) + ilen; c0 = (ucontact_t*)pkg_malloc(olen); if(c0==NULL) { LM_ERR("no more pkg\n"); ul.unlock_udomain((udomain_t*)table, &aor); goto error; } memcpy(c0, ptr, ilen); //c0->domain = {0,0};//NULL;TODO //c0->aor = {0,0};//NULL; c0->next = NULL; c0->prev = NULL; c0->c.s = (char*)c0 + ilen; memcpy(c0->c.s, ptr->c.s, ptr->c.len); c0->c.len = ptr->c.len; p = c0->c.s + c0->c.len; if(ptr->received.s!=NULL) { c0->received.s = p; memcpy(c0->received.s, ptr->received.s, ptr->received.len); c0->received.len = ptr->received.len; p += c0->received.len; } if(ptr->path.s!=NULL) { c0->path.s = p; memcpy(c0->path.s, ptr->path.s, ptr->path.len); c0->path.len = ptr->path.len; p += c0->path.len; } c0->callid.s = p; memcpy(c0->callid.s, ptr->callid.s, ptr->callid.len); c0->callid.len = ptr->callid.len; p += c0->callid.len; if(ptr->user_agent.s!=NULL) { c0->user_agent.s = p; memcpy(c0->user_agent.s, ptr->user_agent.s, ptr->user_agent.len); c0->user_agent.len = ptr->user_agent.len; p += c0->user_agent.len; } if(ptr0==NULL) { rpp->contacts = c0; } else { ptr0->next = c0; c0->prev = ptr0; } n++; ptr0 = c0; ptr = ptr->next; } ul.unlock_udomain((udomain_t*)table, &aor); rpp->nrc = n; LM_DBG("fetched <%d> contacts for <%.*s> in [%.*s]\n", n, aor.len, aor.s, rpp->pname.len, rpp->pname.s); return 1; error: regpv_free_profile(rpp); return -1; }
/*! \brief * Lookup contact in the database and rewrite Request-URI * \return: -1 : not found * -2 : found but method not allowed * -3 : error */ int lookup(struct sip_msg* _m, char* _t, char* _f, char* _s) { unsigned int flags; urecord_t* r; str aor, uri; ucontact_t* ptr,*it; int res; int ret; str path_dst; str flags_s; pv_value_t val; int_str istr; str sip_instance = {0,0},call_id = {0,0}; flags = 0; if (_f && _f[0]!=0) { if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) { LM_ERR("invalid owner uri parameter"); return -1; } for( res=0 ; res< flags_s.len ; res++ ) { switch (flags_s.s[res]) { case 'm': flags |= REG_LOOKUP_METHODFILTER_FLAG; break; case 'b': flags |= REG_LOOKUP_NOBRANCH_FLAG; break; default: LM_WARN("unsuported flag %c \n",flags_s.s[res]); } } } if (_s) { if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) { LM_ERR("failed to get PV value\n"); return -1; } if ( (val.flags&PV_VAL_STR)==0 ) { LM_ERR("PV vals is not string\n"); return -1; } uri = val.rs; } else { if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; } if (extract_aor(&uri, &aor,&sip_instance,&call_id) < 0) { LM_ERR("failed to extract address of record\n"); return -3; } get_act_time(); ul.lock_udomain((udomain_t*)_t, &aor); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res > 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain((udomain_t*)_t, &aor); return -1; } ptr = r->contacts; ret = -1; /* look first for an un-expired and suported contact */ search_valid_contact: while ( (ptr) && !(VALID_CONTACT(ptr,act_time) && (ret=-2) && allowed_method(_m,ptr,flags))) ptr = ptr->next; if (ptr==0) { /* nothing found */ LM_DBG("nothing found !\n"); goto done; } if (sip_instance.len && sip_instance.s) { LM_DBG("ruri has gruu in lookup\n"); /* uri has GRUU */ if (ptr->instance.len-2 != sip_instance.len || memcmp(ptr->instance.s+1,sip_instance.s,sip_instance.len)) { LM_DBG("no match to sip instace - [%.*s] - [%.*s]\n",ptr->instance.len-2,ptr->instance.s+1, sip_instance.len,sip_instance.s); /* not the targeted instance, search some more */ ptr = ptr->next; goto search_valid_contact; } LM_DBG("matched sip instace\n"); } if (call_id.len && call_id.s) { /* decide whether GRUU is expired or not * * first - match call-id */ if (ptr->callid.len != call_id.len || memcmp(ptr->callid.s,call_id.s,call_id.len)) { LM_DBG("no match to call id - [%.*s] - [%.*s]\n",ptr->callid.len,ptr->callid.s, call_id.len,call_id.s); ptr = ptr->next; goto search_valid_contact; } /* matched call-id, check if there are newer contacts with * same sip instace bup newer last_modified */ it = ptr->next; while ( it ) { if (VALID_CONTACT(it,act_time)) { if (it->instance.len-2 == sip_instance.len && memcmp(it->instance.s+1,sip_instance.s,sip_instance.len) == 0) if (it->last_modified > ptr->last_modified) { /* same instance id, but newer modified -> expired GRUU, no match at all */ break; } } it=it->next; } if (it != NULL) { ret = -1; goto done; } } LM_DBG("found a complete match\n"); ret = 1; if (ptr) { LM_DBG("setting as ruri <%.*s>\n",ptr->c.len,ptr->c.s); if (set_ruri(_m, &ptr->c) < 0) { LM_ERR("unable to rewrite Request-URI\n"); ret = -3; goto done; } /* If a Path is present, use first path-uri in favour of * received-uri because in that case the last hop towards the uac * has to handle NAT. - agranig */ if (ptr->path.s && ptr->path.len) { if (get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); ret = -3; goto done; } if (set_path_vector(_m, &ptr->path) < 0) { LM_ERR("failed to set path vector\n"); ret = -3; goto done; } if (set_dst_uri(_m, &path_dst) < 0) { LM_ERR("failed to set dst_uri of Path\n"); ret = -3; goto done; } } else if (ptr->received.s && ptr->received.len) { if (set_dst_uri(_m, &ptr->received) < 0) { ret = -3; goto done; } } set_ruri_q(ptr->q); setbflag( 0, ptr->cflags); if (ptr->sock) _m->force_send_socket = ptr->sock; /* populate the 'attributes' avp */ if (attr_avp_name != -1) { istr.s = ptr->attr; if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) { LM_ERR("Failed to populate attr avp!\n"); } } ptr = ptr->next; } /* Append branches if enabled */ /* If we got to this point and the URI had a ;gr parameter and it was matched * to a contact. No point in branching */ if ( flags®_LOOKUP_NOBRANCH_FLAG || (sip_instance.len && sip_instance.s) ) goto done; LM_DBG("looking for branches\n"); for( ; ptr ; ptr = ptr->next ) { if (VALID_CONTACT(ptr, act_time) && allowed_method(_m,ptr,flags)) { path_dst.len = 0; if(ptr->path.s && ptr->path.len && get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); continue; } /* The same as for the first contact applies for branches * regarding path vs. received. */ LM_DBG("setting branch <%.*s>\n",ptr->c.len,ptr->c.s); if (append_branch(_m,&ptr->c,path_dst.len?&path_dst:&ptr->received, &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) { LM_ERR("failed to append a branch\n"); /* Also give a chance to the next branches*/ continue; } /* populate the 'attributes' avp */ if (attr_avp_name != -1) { istr.s = ptr->attr; if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) { LM_ERR("Failed to populate attr avp!\n"); } } } } done: ul.release_urecord(r); ul.unlock_udomain((udomain_t*)_t, &aor); return ret; }
int save_aux(struct sip_msg* _m, str* forced_binding, char* _d, char* _f, char* _s) { struct save_ctx sctx; contact_t* c; contact_t* forced_c; int st; str uri; str flags_s; pv_value_t val; rerrno = R_FINE; memset( &sctx, 0 , sizeof(sctx)); sctx.max_contacts = -1; sctx.flags = 0; if (_f && _f[0]!=0) { if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) { LM_ERR("invalid flags parameter"); return -1; } for( st=0 ; st< flags_s.len ; st++ ) { switch (flags_s.s[st]) { case 'm': sctx.flags |= REG_SAVE_MEMORY_FLAG; break; case 'r': sctx.flags |= REG_SAVE_NOREPLY_FLAG; break; case 's': sctx.flags |= REG_SAVE_SOCKET_FLAG; break; case 'v': sctx.flags |= REG_SAVE_PATH_RECEIVED_FLAG; break; case 'f': sctx.flags |= REG_SAVE_FORCE_REG_FLAG; break; case 'c': sctx.max_contacts = 0; while (st<flags_s.len-1 && isdigit(flags_s.s[st+1])) { sctx.max_contacts = sctx.max_contacts*10 + flags_s.s[st+1] - '0'; st++; } break; case 'p': if (st<flags_s.len-1) { st++; if (flags_s.s[st]=='2') { sctx.flags |= REG_SAVE_PATH_STRICT_FLAG; break; } if (flags_s.s[st]=='1') { sctx.flags |= REG_SAVE_PATH_LAZY_FLAG; break; } if (flags_s.s[st]=='0') { sctx.flags |= REG_SAVE_PATH_OFF_FLAG; break; } } default: LM_WARN("unsuported flag %c \n",flags_s.s[st]); } } } if(route_type == ONREPLY_ROUTE) sctx.flags |= REG_SAVE_NOREPLY_FLAG; /* if no max_contact per AOR is defined, use the global one */ if (sctx.max_contacts == -1) sctx.max_contacts = max_contacts; if (parse_message(_m) < 0) { goto error; } if (forced_binding) { if (parse_contacts(forced_binding, &forced_c) < 0) { LM_ERR("Unable to parse forced binding [%.*s]\n", forced_binding->len, forced_binding->s); goto error; } /* prevent processing all the headers from the message */ reset_first_contact(); st = 0; c = forced_c; } else { if (check_contacts(_m, &st) > 0) { goto error; } c = get_first_contact(_m); } get_act_time(); if (_s) { if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) { LM_ERR("failed to get PV value\n"); return -1; } if ( (val.flags&PV_VAL_STR)==0 ) { LM_ERR("PV vals is not string\n"); return -1; } uri = val.rs; } else { uri = get_to(_m)->uri; } if (extract_aor( &uri, &sctx.aor) < 0) { LM_ERR("failed to extract Address Of Record\n"); goto error; } if (c == 0) { if (st) { if (star((udomain_t*)_d, &sctx) < 0) goto error; } else { if (no_contacts((udomain_t*)_d, &sctx.aor) < 0) goto error; } } else { if (add_contacts(_m, c, (udomain_t*)_d, &sctx) < 0) goto error; } update_stat(accepted_registrations, 1); if (!is_cflag_set(REG_SAVE_NOREPLY_FLAG) && (send_reply(_m,sctx.flags)<0)) return -1; return 1; error: update_stat(rejected_registrations, 1); if ( !is_cflag_set(REG_SAVE_NOREPLY_FLAG) ) send_reply(_m,sctx.flags); return 0; }
/*! \brief * Lookup contact in the database and rewrite Request-URI * \return: -1 : not found * -2 : found but method not allowed * -3 : error */ int lookup(struct sip_msg* _m, udomain_t* _d, str* _uri) { urecord_t* r; str aor, uri; sip_uri_t puri; ucontact_t* ptr = 0; int res; int ret; str path_dst; flag_t old_bflags; int i; str inst = {0}; unsigned int ahash = 0; sr_xavp_t *xavp=NULL; sr_xavp_t *list=NULL; str xname = {"ruid", 4}; sr_xval_t xval; ret = -1; if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; if (extract_aor((_uri)?_uri:&uri, &aor, &puri) < 0) { LM_ERR("failed to extract address of record\n"); return -3; } /* check if gruu */ if(puri.gr.s!=NULL) { if(puri.gr_val.len>0) { /* pub-gruu */ inst = puri.gr_val; LM_DBG("looking up pub gruu [%.*s]\n", inst.len, inst.s); } else { /* temp-gruu */ ahash = 0; inst = puri.user; for(i=inst.len-1; i>=0; i--) { if(inst.s[i]==REG_GRUU_SEP) break; ahash <<= 4; if(inst.s[i] >='0' && inst.s[i] <='9') ahash+=inst.s[i] -'0'; else if (inst.s[i] >='a' && inst.s[i] <='f') ahash+=inst.s[i] -'a'+10; else if (inst.s[i] >='A' && inst.s[i] <='F') ahash+=inst.s[i] -'A'+10; else { LM_ERR("failed to extract temp gruu - invalid hash\n"); return -3; } } if(i<0) { LM_ERR("failed to extract temp gruu - invalid format\n"); return -3; } inst.len = i; LM_DBG("looking up temp gruu [%u / %.*s]\n", ahash, inst.len, inst.s); } } get_act_time(); if(puri.gr.s==NULL || puri.gr_val.len>0) { /* aor or pub-gruu lookup */ ul.lock_udomain(_d, &aor); res = ul.get_urecord(_d, &aor, &r); if (res > 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain(_d, &aor); return -1; } ptr = r->contacts; ret = -1; /* look first for an un-expired and suported contact */ while (ptr) { if(VALID_CONTACT(ptr,act_time)) { if(allowed_method(_m,ptr)) { /* match on instance, if pub-gruu */ if(inst.len>0) { if(reg_cmp_instances(&inst, &ptr->instance)==0) { /* pub-gruu - found by instance */ LM_DBG("contact for [%.*s] found by pub gruu [%.*s]\n", aor.len, ZSW(aor.s), inst.len, inst.s); break; } } else { /* no-gruu - found by address */ LM_DBG("contact for [%.*s] found by address\n", aor.len, ZSW(aor.s)); break; } } else { LM_DBG("contact for [%.*s] cannot handle the SIP method\n", aor.len, ZSW(aor.s)); ret = -2; } } ptr = ptr->next; } if (ptr==0) { /* nothing found */ LM_DBG("'%.*s' has no valid contact in usrloc\n", aor.len, ZSW(aor.s)); goto done; } } else { /* temp-gruu lookup */ res = ul.get_urecord_by_ruid(_d, ahash, &inst, &r, &ptr); if(res<0) { LM_DBG("temp gruu '%.*s' not found in usrloc\n", aor.len, ZSW(aor.s)); return -1; } aor = *ptr->aor; /* test if un-expired and suported contact */ if( (ptr) && !(VALID_CONTACT(ptr,act_time) && (ret=-2) && allowed_method(_m,ptr))) goto done; LM_DBG("contact for [%.*s] found by temp gruu [%.*s / %u]\n", aor.len, ZSW(aor.s), inst.len, inst.s, ahash); } ret = 1; if (ptr) { if (rewrite_uri(_m, &ptr->c) < 0) { LM_ERR("unable to rewrite Request-URI\n"); ret = -3; goto done; } /* reset next hop address */ reset_dst_uri(_m); /* add xavp with details of the record (ruid, ...) */ if(reg_xavp_rcd.s!=NULL) { list = xavp_get(®_xavp_rcd, NULL); xavp = list; memset(&xval, 0, sizeof(sr_xval_t)); xval.type = SR_XTYPE_STR; xval.v.s = ptr->ruid; xavp_add_value(&xname, &xval, &xavp); if(list==NULL) { /* no reg_xavp_rcd xavp in root list - add it */ xval.type = SR_XTYPE_XAVP; xval.v.xavp = xavp; xavp_add_value(®_xavp_rcd, &xval, NULL); } } /* If a Path is present, use first path-uri in favour of * received-uri because in that case the last hop towards the uac * has to handle NAT. - agranig */ if (ptr->path.s && ptr->path.len) { if (get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); ret = -3; goto done; } if (set_path_vector(_m, &ptr->path) < 0) { LM_ERR("failed to set path vector\n"); ret = -3; goto done; } if (set_dst_uri(_m, &path_dst) < 0) { LM_ERR("failed to set dst_uri of Path\n"); ret = -3; goto done; } } else if (ptr->received.s && ptr->received.len) { if (set_dst_uri(_m, &ptr->received) < 0) { ret = -3; goto done; } } if (ptr->instance.len) { if (set_instance(_m, &(ptr->instance)) < 0) { ret = -3; goto done; } } _m->reg_id = ptr->reg_id; if (ptr->ruid.len) { if (set_ruid(_m, &(ptr->ruid)) < 0) { ret = -3; goto done; } } if (ptr->user_agent.len) { if (set_ua(_m, &(ptr->user_agent)) < 0) { ret = -3; goto done; } } set_ruri_q(ptr->q); old_bflags = 0; getbflagsval(0, &old_bflags); setbflagsval(0, old_bflags|ptr->cflags); if (ptr->sock) set_force_socket(_m, ptr->sock); if(ptr->xavp!=NULL) { xavp = xavp_clone_level_nodata(ptr->xavp); if(xavp_add(xavp, NULL)<0) { ret = -3; goto done; } } ptr = ptr->next; } /* if was gruu, no more branches */ if(inst.len>0) goto done; /* Append branches if enabled */ if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done; for( ; ptr ; ptr = ptr->next ) { if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { path_dst.len = 0; if(ptr->path.s && ptr->path.len && get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); continue; } /* The same as for the first contact applies for branches * regarding path vs. received. */ LM_DBG("instance is %.*s\n", ptr->instance.len, ptr->instance.s); if (append_branch(_m, &ptr->c, path_dst.len?&path_dst:&ptr->received, &ptr->path, ptr->q, ptr->cflags, ptr->sock, ptr->instance.len?&(ptr->instance):0, ptr->instance.len?ptr->reg_id:0, &ptr->ruid, &ptr->user_agent) == -1) { LM_ERR("failed to append a branch\n"); /* Also give a chance to the next branches*/ continue; } if(ptr->xavp!=NULL) { xavp = xavp_clone_level_nodata(ptr->xavp); if(xavp_insert(xavp, nr_branches, NULL)<0) { ret = -3; goto done; } } } } done: ul.release_urecord(r); ul.unlock_udomain(_d, &aor); return ret; }
/*! \brief * Lookup contact in the database and rewrite Request-URI * \return: -1 : not found * -2 : found but method not allowed * -3 : error */ int lookup(struct sip_msg* _m, char* _t, char* _f, char* _s) { unsigned int flags; urecord_t* r; str aor, uri; ucontact_t* ptr,*it; int res; int ret; str path_dst; str flags_s; char* ua = NULL; char* re_end = NULL; int re_len = 0; char tmp; regex_t ua_re; int regexp_flags = 0; regmatch_t ua_match; pv_value_t val; int_str istr; str sip_instance = {0,0},call_id = {0,0}; /* branch index */ int idx; /* temporary branch values*/ int tlen; char *turi; qvalue_t tq; flags = 0; if (_f && _f[0]!=0) { if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) { LM_ERR("invalid owner uri parameter"); return -1; } for( res=0 ; res< flags_s.len ; res++ ) { switch (flags_s.s[res]) { case 'm': flags |= REG_LOOKUP_METHODFILTER_FLAG; break; case 'b': flags |= REG_LOOKUP_NOBRANCH_FLAG; break; case 'r': flags |= REG_BRANCH_AOR_LOOKUP_FLAG; break; case 'u': if (flags_s.s[res+1] != '/') { LM_ERR("no regexp after 'u' flag"); break; } res++; if ((re_end = strrchr(flags_s.s+res+1, '/')) == NULL) { LM_ERR("no regexp after 'u' flag"); break; } res++; re_len = re_end-flags_s.s-res; if (re_len == 0) { LM_ERR("empty regexp"); break; } ua = flags_s.s+res; flags |= REG_LOOKUP_UAFILTER_FLAG; LM_DBG("found regexp /%.*s/", re_len, ua); res += re_len; break; case 'i': regexp_flags |= REG_ICASE; break; case 'e': regexp_flags |= REG_EXTENDED; break; default: LM_WARN("unsuported flag %c \n",flags_s.s[res]); } } } if (flags®_BRANCH_AOR_LOOKUP_FLAG) { /* extract all the branches for further usage */ nbranches = 0; while ( (turi=get_branch(nbranches, &tlen, &tq, NULL, NULL, NULL, NULL)) ) { /* copy uri */ branch_uris[nbranches].s = urimem[nbranches]; if (tlen) { memcpy(branch_uris[nbranches].s, turi, tlen); branch_uris[nbranches].len = tlen; } else { *branch_uris[nbranches].s = '\0'; branch_uris[nbranches].len = 0; } nbranches++; } clear_branches(); idx=0; } if (_s) { if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) { LM_ERR("failed to get PV value\n"); return -1; } if ( (val.flags&PV_VAL_STR)==0 ) { LM_ERR("PV vals is not string\n"); return -1; } uri = val.rs; } else { if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; } if (extract_aor(&uri, &aor,&sip_instance,&call_id) < 0) { LM_ERR("failed to extract address of record\n"); return -3; } get_act_time(); ul.lock_udomain((udomain_t*)_t, &aor); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res > 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain((udomain_t*)_t, &aor); return -1; } if (flags & REG_LOOKUP_UAFILTER_FLAG) { tmp = *(ua+re_len); *(ua+re_len) = '\0'; if (regcomp(&ua_re, ua, regexp_flags) != 0) { LM_ERR("bad regexp '%s'\n", ua); *(ua+re_len) = tmp; return -1; } *(ua+re_len) = tmp; } ptr = r->contacts; ret = -1; /* look first for an un-expired and suported contact */ search_valid_contact: while ( (ptr) && !(VALID_CONTACT(ptr,act_time) && (ret=-2) && allowed_method(_m,ptr,flags))) ptr = ptr->next; if (ptr==0) { /* nothing found */ LM_DBG("nothing found !\n"); goto done; } ua_re_check( ret = -1; ptr = ptr->next; goto search_valid_contact ); if (sip_instance.len && sip_instance.s) { LM_DBG("ruri has gruu in lookup\n"); /* uri has GRUU */ if (ptr->instance.len-2 != sip_instance.len || memcmp(ptr->instance.s+1,sip_instance.s,sip_instance.len)) { LM_DBG("no match to sip instace - [%.*s] - [%.*s]\n",ptr->instance.len-2,ptr->instance.s+1, sip_instance.len,sip_instance.s); /* not the targeted instance, search some more */ ptr = ptr->next; goto search_valid_contact; } LM_DBG("matched sip instace\n"); } if (call_id.len && call_id.s) { /* decide whether GRUU is expired or not * * first - match call-id */ if (ptr->callid.len != call_id.len || memcmp(ptr->callid.s,call_id.s,call_id.len)) { LM_DBG("no match to call id - [%.*s] - [%.*s]\n",ptr->callid.len,ptr->callid.s, call_id.len,call_id.s); ptr = ptr->next; goto search_valid_contact; } /* matched call-id, check if there are newer contacts with * same sip instace bup newer last_modified */ it = ptr->next; while ( it ) { if (VALID_CONTACT(it,act_time)) { if (it->instance.len-2 == sip_instance.len && sip_instance.s && memcmp(it->instance.s+1,sip_instance.s,sip_instance.len) == 0) if (it->last_modified > ptr->last_modified) { /* same instance id, but newer modified -> expired GRUU, no match at all */ break; } } it=it->next; } if (it != NULL) { ret = -1; goto done; } } LM_DBG("found a complete match\n"); ret = 1; if (ptr) { LM_DBG("setting as ruri <%.*s>\n",ptr->c.len,ptr->c.s); if (set_ruri(_m, &ptr->c) < 0) { LM_ERR("unable to rewrite Request-URI\n"); ret = -3; goto done; } /* If a Path is present, use first path-uri in favour of * received-uri because in that case the last hop towards the uac * has to handle NAT. - agranig */ if (ptr->path.s && ptr->path.len) { if (get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); ret = -3; goto done; } if (set_path_vector(_m, &ptr->path) < 0) { LM_ERR("failed to set path vector\n"); ret = -3; goto done; } if (set_dst_uri(_m, &path_dst) < 0) { LM_ERR("failed to set dst_uri of Path\n"); ret = -3; goto done; } } else if (ptr->received.s && ptr->received.len) { if (set_dst_uri(_m, &ptr->received) < 0) { ret = -3; goto done; } } set_ruri_q( _m, ptr->q); setbflag( _m, 0, ptr->cflags); if (ptr->sock) _m->force_send_socket = ptr->sock; /* populate the 'attributes' avp */ if (attr_avp_name != -1) { istr.s = ptr->attr; if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) { LM_ERR("Failed to populate attr avp!\n"); } } ptr = ptr->next; } /* Append branches if enabled */ /* If we got to this point and the URI had a ;gr parameter and it was matched * to a contact. No point in branching */ if ( flags®_LOOKUP_NOBRANCH_FLAG || (sip_instance.len && sip_instance.s) ) goto done; LM_DBG("looking for branches\n"); do { for( ; ptr ; ptr = ptr->next ) { if (VALID_CONTACT(ptr, act_time) && allowed_method(_m,ptr,flags)) { path_dst.len = 0; if(ptr->path.s && ptr->path.len && get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); continue; } ua_re_check(continue); /* The same as for the first contact applies for branches * regarding path vs. received. */ LM_DBG("setting branch <%.*s>\n",ptr->c.len,ptr->c.s); if (append_branch(_m,&ptr->c,path_dst.len?&path_dst:&ptr->received, &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) { LM_ERR("failed to append a branch\n"); /* Also give a chance to the next branches*/ continue; } /* populate the 'attributes' avp */ if (attr_avp_name != -1) { istr.s = ptr->attr; if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) { LM_ERR("Failed to populate attr avp!\n"); } } } } /* 0 branches condition also filled; idx initially -1*/ if (!(flags®_BRANCH_AOR_LOOKUP_FLAG) || idx == nbranches) goto done; /* relsease old aor lock */ ul.unlock_udomain((udomain_t*)_t, &aor); ul.release_urecord(r, 0); /* idx starts from -1 */ uri = branch_uris[idx]; if (extract_aor(&uri, &aor, NULL, &call_id) < 0) { LM_ERR("failed to extract address of record for branch uri\n"); return -3; } /* release old urecord */ /* get lock on new aor */ LM_DBG("getting contacts from aor [%.*s]" "in branch %d\n", aor.len, aor.s, idx); ul.lock_udomain((udomain_t*)_t, &aor); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res > 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); goto done; } idx++; ptr = r->contacts; } while (1);
/* * Lookup contact in the database and rewrite Request-URI */ int lookup(struct sip_msg* _m, char* _t, char* _s) { urecord_t* r; str aor, uri; ucontact_t* ptr; int res; unsigned int nat; nat = 0; if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; if (extract_aor(&uri, &aor) < 0) { LOG(L_ERR, "lookup(): Error while extracting address of record\n"); return -1; } get_act_time(); ul.lock_udomain((udomain_t*)_t); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res < 0) { LOG(L_ERR, "lookup(): Error while querying usrloc\n"); ul.unlock_udomain((udomain_t*)_t); return -2; } if (res > 0) { DBG("lookup(): '%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain((udomain_t*)_t); return -3; } ptr = r->contacts; while ((ptr) && ((ptr->expires <= act_time) || (ptr->state >= CS_ZOMBIE_N))) ptr = ptr->next; if (ptr) { if (rwrite(_m, &ptr->c) < 0) { LOG(L_ERR, "lookup(): Unable to rewrite Request-URI\n"); ul.unlock_udomain((udomain_t*)_t); return -4; } nat |= ptr->flags & FL_NAT; ptr = ptr->next; } else { /* All contacts expired */ ul.unlock_udomain((udomain_t*)_t); return -5; } /* Append branches if enabled */ if (!append_branches) goto skip; while(ptr) { if (ptr->expires > act_time && (ptr->state < CS_ZOMBIE_N)) { if (append_branch(_m, ptr->c.s, ptr->c.len) == -1) { LOG(L_ERR, "lookup(): Error while appending a branch\n"); goto skip; /* Return OK here so the function succeeds */ } nat |= ptr->flags & FL_NAT; } ptr = ptr->next; } skip: ul.unlock_udomain((udomain_t*)_t); if (nat) setflag(_m, nat_flag); return 1; }