/* * Make a private copy of the string and assign it to dst_uri */ int set_dst_uri(struct sip_msg* const msg, const str* const uri) { char* ptr; if (unlikely(!msg || !uri)) { LOG(L_ERR, "set_dst_uri: Invalid parameter value\n"); return -1; } if (unlikely(uri->len == 0)) { reset_dst_uri(msg); } else if (msg->dst_uri.s && (msg->dst_uri.len >= uri->len)) { memcpy(msg->dst_uri.s, uri->s, uri->len); msg->dst_uri.len = uri->len; } else { ptr = (char*)pkg_malloc(uri->len); if (!ptr) { LOG(L_ERR, "set_dst_uri: Not enough memory\n"); return -1; } memcpy(ptr, uri->s, uri->len); if (msg->dst_uri.s) pkg_free(msg->dst_uri.s); msg->dst_uri.s = ptr; msg->dst_uri.len = uri->len; } return 0; }
/*! \brief * Lookup contact in the database and rewrite Request-URI * \return: 1 : contacts found and returned * -1 : not found * -2 : error */ int lookup_transport(struct sip_msg* _m, udomain_t* _d, str* _uri) { str uri; pcontact_t* pcontact; char tmp[MAX_URI_SIZE]; char srcip[20]; str received_host; str tmp_s; int ret = 1; if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); received_host.s = srcip; //now lookup in usrloc ul.lock_udomain(_d, &uri, &received_host, _m->rcv.src_port); if (ul.get_pcontact(_d, &uri, &received_host, _m->rcv.src_port, &pcontact) != 0) { //need to insert new contact LM_WARN("received request for contact that we don't know about\n"); ret = -1; goto done; } if (pcontact->received_proto != _m->rcv.proto) { reset_dst_uri(_m); memset(tmp, 0, MAX_URI_SIZE); switch (pcontact->received_proto) { case PROTO_TCP: snprintf(tmp, MAX_URI_SIZE, "%.*s;transport=tcp", pcontact->aor.len, pcontact->aor.s); break; case PROTO_UDP: snprintf(tmp, MAX_URI_SIZE, "%.*s;transport=udp", pcontact->aor.len, pcontact->aor.s); break; default: LM_WARN("unsupported transport [%d]\n", pcontact->received_proto); ret = -2; goto done; } tmp_s.s = tmp; tmp_s.len = strlen(tmp); if (set_dst_uri(_m, &tmp_s) < 0) { LM_ERR("failed to set dst_uri for terminating UE\n"); ret = -2; goto done; } LM_DBG("Changed dst URI transport for UE to [%.*s]\n", tmp_s.len, tmp_s.s); } done: ul.unlock_udomain(_d, &uri, &received_host, _m->rcv.src_port); return ret; }
int reset_ruri_branch(sip_msg_t *msg) { if(msg==NULL) return -1; reset_dst_uri(msg); reset_path_vector(msg); set_ruri_q(Q_UNSPECIFIED); reset_force_socket(msg); setbflagsval(0, 0); reset_instance(msg); msg->reg_id = 0; return 0; }
static int lua_sr_resetdsturi (lua_State *L) { sr_lua_env_t *env_L; env_L = sr_lua_env_get(); if(env_L->msg==NULL) { LM_WARN("invalid parameters from Lua env\n"); return app_lua_return_false(L); } reset_dst_uri(env_L->msg); return app_lua_return_true(L); }
/*only the content*/ void free_sip_msg(struct sip_msg* const msg) { reset_new_uri(msg); reset_dst_uri(msg); reset_path_vector(msg); reset_instance(msg); reset_ruid(msg); reset_ua(msg); if (msg->headers) free_hdr_field_lst(msg->headers); if (msg->body && msg->body->free) msg->body->free(&msg->body); if (msg->add_rm) free_lump_list(msg->add_rm); if (msg->body_lumps) free_lump_list(msg->body_lumps); if (msg->reply_lump) free_reply_lump(msg->reply_lump); msg_ldata_reset(msg); /* don't free anymore -- now a pointer to a static buffer */ # ifdef DYN_BUF pkg_free(msg->buf); # endif }
/*! \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; }
int sbranch_set_ruri(sip_msg_t *msg) { str sv; flag_t old_bflags; branch_t *br; int ret; ret = 0; br = &_pv_sbranch; if(br->len==0) return -1; sv.s = br->uri; sv.len = br->len; if (rewrite_uri(msg, &sv) < 0) { LM_ERR("unable to rewrite Request-URI\n"); ret = -3; goto error; } /* reset next hop address */ reset_dst_uri(msg); if(br->dst_uri_len>0) { sv.s = br->dst_uri; sv.len = br->dst_uri_len; if (set_dst_uri(msg, &sv) < 0) { ret = -3; goto error; } } reset_path_vector(msg); if(br->path_len==0) { sv.s = br->path; sv.len = br->path_len; if(set_path_vector(msg, &sv) < 0) { ret = -4; goto error; } } reset_instance(msg); if (br->instance_len) { sv.s = br->instance; sv.len = br->instance_len; if (set_instance(msg, &sv) < 0) { ret = -5; goto error; } } reset_ruid(msg); if (br->ruid_len) { sv.s = br->ruid; sv.len = br->ruid_len; if (set_ruid(msg, &sv) < 0) { ret = -6; goto error; } } reset_ua(msg); if (br->location_ua_len) { sv.s = br->location_ua; sv.len = br->location_ua_len; if (set_ua(msg, &sv) < 0) { ret = -7; goto error; } } if (br->force_send_socket) set_force_socket(msg, br->force_send_socket); msg->reg_id = br->reg_id; set_ruri_q(br->q); old_bflags = 0; getbflagsval(0, &old_bflags); setbflagsval(0, old_bflags|br->flags); return 0; error: 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, 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; }
/* * Adds to request a new destination set that includes all highest * priority class contacts in contacts_avp. Request URI is rewritten with * first contact and the remaining contacts (if any) are added as branches. * Removes used contacts from contacts_avp. Returns 1, if contacts_avp * was not empty and a destination set was successfully added. Returns -2, * if contacts_avp was empty and thus there was nothing to do. * Returns -1 in case of an error. */ int t_next_contacts(struct sip_msg* msg, char* key, char* value) { struct usr_avp *avp, *prev; int_str val; str uri, dst, path; struct socket_info *sock; unsigned int flags; struct search_state st; /* Check if contacts_avp has been defined */ if (contacts_avp.n == 0) { LM_ERR("feature has been disabled - " "to enable define contacts_avp module parameter"); return -1; } /* Load Request-URI and branches */ /* Find first contacts_avp value */ avp = search_first_avp(contacts_avp_type, contacts_avp, &val, &st); if (!avp) { LM_DBG("no AVPs - we are done!\n"); return -2; } LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s)); if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags) == 0) { LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s)); destroy_avp(avp); return -1; } /* Rewrite Request-URI */ rewrite_uri(msg, &uri); if (dst.s && dst.len) set_dst_uri(msg, &dst); else reset_dst_uri(msg); if (path.s && path.len) set_path_vector(msg, &path); else reset_path_vector(msg); set_force_socket(msg, sock); setbflagsval(0, flags); if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } /* Append branches until out of branches or Q_FLAG is set */ prev = avp; while ((avp = search_next_avp(&st, &val))) { destroy_avp(prev); LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s)); if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags) == 0) { LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s)); destroy_avp(avp); return -1; } if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) { LM_ERR("appending branch failed\n"); destroy_avp(avp); return -1; } if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } prev = avp; } destroy_avp(prev); return 1; }
int rtjson_init_serial(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp) { srjson_t *tj = NULL; srjson_t *nj = NULL; srjson_t *rj = NULL; str val; unsigned int bflags = 0; unsigned int old_bflags = 0; struct socket_info* fsocket = NULL; tj = srjson_GetObjectItem(jdoc, jdoc->root, "routes"); if(tj==NULL || tj->type!=srjson_Array || tj->child==NULL) { LM_ERR("missing or invalid routes field\n"); goto error; } nj = tj->child; clear_branches(); rj = srjson_GetObjectItem(jdoc, nj, "uri"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite r-uri to: [%.*s]\n", val.len, val.s); if (rewrite_uri(msg, &val) < 0) { LM_ERR("unable to rewrite Request-URI\n"); goto error; } } reset_dst_uri(msg); reset_path_vector(msg); reset_instance(msg); reset_ruid(msg); reset_ua(msg); reset_force_socket(msg); msg->reg_id = 0; set_ruri_q(0); rj = srjson_GetObjectItem(jdoc, nj, "dst_uri"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite dst-uri to: [%.*s]\n", val.len, val.s); if (set_dst_uri(msg, &val) < 0) { LM_ERR("unable to set destination uri\n"); goto error; } } rj = srjson_GetObjectItem(jdoc, nj, "path"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite path to: [%.*s]\n", val.len, val.s); if (set_path_vector(msg, &val) < 0) { LM_ERR("unable to set path\n"); goto error; } } rj = srjson_GetObjectItem(jdoc, nj, "socket"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("trying to set send socket to: [%.*s]\n", val.len, val.s); fsocket = lookup_local_socket(&val); if(fsocket) { set_force_socket(msg, fsocket); } } rj = srjson_GetObjectItem(jdoc, nj, "branch_flags"); if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) { bflags = SRJSON_GET_UINT(rj); old_bflags = 0; getbflagsval(0, &old_bflags); setbflagsval(0, old_bflags|bflags); } iavp->val.v.i++; return 0; error: return -1; }