int set_path_vector(struct sip_msg* msg, str* path) { char* ptr; if (unlikely(!msg || !path)) { LM_ERR("invalid parameter value\n"); return -1; } if (unlikely(path->len == 0)) { reset_path_vector(msg); } else if (msg->path_vec.s && (msg->path_vec.len >= path->len)) { memcpy(msg->path_vec.s, path->s, path->len); msg->path_vec.len = path->len; } else { ptr = (char*)pkg_malloc(path->len); if (!ptr) { LM_ERR("not enough pkg memory\n"); return -1; } memcpy(ptr, path->s, path->len); if (msg->path_vec.s) pkg_free(msg->path_vec.s); msg->path_vec.s = ptr; msg->path_vec.len = path->len; } return 0; }
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; }
/*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 }
/** * Creates new "main" branch by making copy of branch-failure branch. * Currently the following branch attributes are included: * request-uri, ruid, path, instance, and branch flags. */ static int w_t_reuse_branch(sip_msg_t* msg, char *p1, char *p2) { tm_cell_t *t; int branch; if (msg == NULL) return -1; /* first get the transaction */ if (_tmx_tmb.t_check(msg, 0) == -1) return -1; if ((t = _tmx_tmb.t_gett()) == 0) { LM_ERR("no transaction\n"); return -1; } switch (get_route_type()) { case BRANCH_FAILURE_ROUTE: /* use the reason of the winning reply */ if ((branch = _tmx_tmb.t_get_picked_branch()) < 0) { LM_CRIT("no picked branch (%d) for a final response" " in MODE_ONFAILURE\n", branch); return -1; } if(rewrite_uri(msg, &(t->uac[branch].uri))<0) { LM_WARN("failed to rewrite the r-uri\n"); } set_ruid(msg, &(t->uac[branch].ruid)); if (t->uac[branch].path.len) { if(set_path_vector(msg, &(t->uac[branch].path))<0) { LM_WARN("failed to set the path vector\n"); } } else { reset_path_vector(msg); } setbflagsval(0, t->uac[branch].branch_flags); set_instance(msg, &(t->uac[branch].instance)); return 1; default: LM_ERR("unsupported route_type %d\n", get_route_type()); return -1; } }
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; }
/* * 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; }
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; int novariation = 0; 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"); free_rr(&route); goto error; } if (parse_params(&puri.params, CLASS_URI, &hooks, ¶ms) != 0) { LM_ERR("Failed to parse Path: URI parameters\n"); free_rr(&route); goto error; } /* Not interested in param body - just the hooks */ free_params(params); if (!hooks.uri.ob) { /* No ;ob parameter to top Path: URI - no outbound */ use_ob = 0; } free_rr(&route); } 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; novariation = is_cflag_set(REG_SAVE_NOVARIATION_FL)? 1:0; 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, novariation)) < 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; if (path_enabled && path_mode != PATH_MODE_OFF) { reset_path_vector(_m); } 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); if (R_TOO_MANY == rerrno) return -2; /* for all other */ return 0; }
void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elapsed_msecs) { struct cell *t = 0; int rc = -1, experimental_rc = -1; int result = CSCF_RETURN_TRUE; saved_transaction_t* data = 0; str xml_data = {0, 0}, ccf1 = {0, 0}, ccf2 = {0, 0}, ecf1 = {0, 0}, ecf2 = {0, 0}; ims_subscription* s = 0; rerrno = R_FINE; if (!param) { LM_DBG("No transaction data this must have been called from usrloc cb impu deleted - just log result code and then exit"); cxdx_get_result_code(saa, &rc); cxdx_get_experimental_result_code(saa, &experimental_rc); if (saa) cdpb.AAAFreeMessage(&saa); if (!rc && !experimental_rc) { LM_ERR("bad SAA result code\n"); return; } switch (rc) { case -1: LM_DBG("Received Diameter error\n"); return; case AAA_UNABLE_TO_COMPLY: LM_DBG("Unable to comply\n"); return; case AAA_SUCCESS: LM_DBG("received AAA success\n"); return; default: LM_ERR("Unknown error\n"); return; } } else { LM_DBG("There is transaction data this must have been called from save or assign server unreg"); data = (saved_transaction_t*) param; if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); rerrno = R_SAR_FAILED; goto error_no_send; } set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to); get_act_time(); if (is_timeout) { update_stat(stat_sar_timeouts, 1); LM_ERR("Transaction timeout - did not get SAA\n"); rerrno = R_SAR_FAILED; goto error; } if (!saa) { LM_ERR("Error sending message via CDP\n"); rerrno = R_SAR_FAILED; goto error; } update_stat(sar_replies_received, 1); update_stat(sar_replies_response_time, elapsed_msecs); /* check and see that all the required headers are available and can be parsed */ if (parse_message_for_register(t->uas.request) < 0) { LM_ERR("Unable to parse register message correctly\n"); rerrno = R_SAR_FAILED; goto error; } cxdx_get_result_code(saa, &rc); cxdx_get_experimental_result_code(saa, &experimental_rc); cxdx_get_charging_info(saa, &ccf1, &ccf2, &ecf1, &ecf2); if (!rc && !experimental_rc) { LM_ERR("bad SAA result code\n"); rerrno = R_SAR_FAILED; goto error; } switch (rc) { case -1: LM_DBG("Received Diameter error\n"); rerrno = R_SAR_FAILED; goto error; case AAA_UNABLE_TO_COMPLY: LM_DBG("Unable to comply\n"); rerrno = R_SAR_FAILED; goto error; case AAA_SUCCESS: LM_DBG("received AAA success for SAR - SAA\n"); break; default: LM_ERR("Unknown error\n"); rerrno = R_SAR_FAILED; goto error; } //success //if this is from a save (not a server assign unreg) and expires is zero we don't update usrloc as this is a dereg and usrloc was updated previously if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER && data->expires == 0) { LM_DBG("no need to update usrloc - already done for de-reg\n"); result = CSCF_RETURN_TRUE; goto success; } xml_data = cxdx_get_user_data(saa); /*If there is XML user data we must be able to parse it*/ if (xml_data.s && xml_data.len > 0) { LM_DBG("Parsing user data string from SAA\n"); s = parse_user_data(xml_data); if (!s) { LM_ERR("Unable to parse user data XML string\n"); rerrno = R_SAR_FAILED; goto error; } LM_DBG("Successfully parse user data XML setting ref to 1 (we are referencing it)\n"); s->ref_count = 1; //no need to lock as nobody else will be referencing this piece of memory just yet } else { if (data->require_user_data) { LM_ERR("We require User data for this assignment/register and none was supplied\n"); rerrno = R_SAR_FAILED; result = CSCF_RETURN_FALSE; goto done; } } if (data->sar_assignment_type == AVP_IMS_SAR_REGISTRATION || data->sar_assignment_type == AVP_IMS_SAR_RE_REGISTRATION) { if (build_p_associated_uri(s) != 0) { LM_ERR("Unable to build p_associated_uri\n"); rerrno = R_SAR_FAILED; goto error; } } //here we update the contacts and also build the new contact header for the 200 OK reply if (update_contacts(t->uas.request, data->domain, &data->public_identity, data->sar_assignment_type, &s, &ccf1, &ccf2, &ecf1, &ecf2, &data->contact_header) <= 0) { LM_ERR("Error processing REGISTER\n"); rerrno = R_SAR_FAILED; goto error; } if (data->contact_header) { LM_DBG("Updated contacts: %.*s\n", data->contact_header->data_len, data->contact_header->buf); } else { LM_DBG("Updated unreg contact\n"); } } success: update_stat(accepted_registrations, 1); done: if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER) reg_send_reply_transactional(t->uas.request, data->contact_header, t); LM_DBG("DBG:SAR Async CDP callback: ... Done resuming transaction\n"); create_return_code(result); //release our reference on subscription (s) if (s) ul.unref_subscription(s); //free memory if (saa) cdpb.AAAFreeMessage(&saa); if (t) { del_nonshm_lump_rpl(&t->uas.request->reply_lump); tmb.unref_cell(t); } //free path vector pkg memory reset_path_vector(t->uas.request); tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_transaction_data(data); return; error: create_return_code(-2); if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER) reg_send_reply_transactional(t->uas.request, data->contact_header, t); error_no_send: //if we don't have the transaction then we can't send a transaction response update_stat(rejected_registrations, 1); //free memory if (saa) cdpb.AAAFreeMessage(&saa); if (t) { del_nonshm_lump_rpl(&t->uas.request->reply_lump); tmb.unref_cell(t); } tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_transaction_data(data); return; }