void async_cdp_uar_callback(int is_timeout, void *param, AAAMessage *uaa, long elapsed_msecs) { struct run_act_ctx ra_ctx; str server_name; int *m_capab = 0, m_capab_cnt = 0; int *o_capab = 0, o_capab_cnt = 0; str *p_server_names = 0; int p_server_names_cnt = 0; int rc = -1, experimental_rc = -1; saved_uar_transaction_t* data = (saved_uar_transaction_t*) param; struct cell *t = 0; int result = CSCF_RETURN_TRUE; scscf_entry *list = 0; if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("ERROR: t_continue: transaction not found\n"); //result = CSCF_RETURN_ERROR;//not needed we set by default to error! goto error; } if (is_timeout != 0) { LM_ERR("Error timeout when sending message via CDP\n"); update_stat(stat_uar_timeouts, 1); goto error; } //update stats on response time update_stat(uar_replies_received, 1); update_stat(uar_replies_response_time, elapsed_msecs); if (!uaa) { LM_ERR("Error sending message via CDP\n"); //result = CSCF_RETURN_ERROR;//not needed we set by default to error! goto error; } server_name = cxdx_get_server_name(uaa); if (!server_name.len) { cxdx_get_capabilities(uaa, &m_capab, &m_capab_cnt, &o_capab, &o_capab_cnt, &p_server_names, &p_server_names_cnt); } cxdx_get_result_code(uaa, &rc); cxdx_get_experimental_result_code(uaa, &experimental_rc); if (rc && !experimental_rc) { LM_ERR("No result code or experimental result code - responding 480\n"); cscf_reply_transactional_async(t, t->uas.request, 480, MSG_480_DIAMETER_MISSING_AVP); result = CSCF_RETURN_FALSE; goto done; } switch (rc) { case -1: switch (experimental_rc) { case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN: /* Check, if route is set: */ if (route_uar_user_unknown_no >= 0) { /* exec routing script */ init_run_actions_ctx(&ra_ctx); if (run_actions(&ra_ctx, main_rt.rlist[route_uar_user_unknown_no], t->uas.request) < 0) { LM_DBG("ims_icscf: error while trying script\n"); } } else { cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_USER_UNKNOWN); } LM_ERR("RC_IMS_DIAMETER_ERROR_USER_UNKNOWN\n"); result = CSCF_RETURN_FALSE; goto done; case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH: LM_ERR("RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_IDENTITIES_DONT_MATCH); result = CSCF_RETURN_FALSE; goto done; case RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED: LM_ERR("RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_ROAMING_NOT_ALLOWED); result = CSCF_RETURN_FALSE; goto done; case RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED: LM_ERR("RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_IDENTITY_NOT_REGISTERED); result = CSCF_RETURN_FALSE; goto done; case RC_IMS_DIAMETER_FIRST_REGISTRATION: goto success; case RC_IMS_DIAMETER_SUBSEQUENT_REGISTRATION: goto success; case RC_IMS_DIAMETER_SERVER_SELECTION: goto success; default: LM_ERR("MSG_403_UNKOWN_EXPERIMENTAL_RC returning 500\n"); cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_UNKOWN_EXPERIMENTAL_RC); result = CSCF_RETURN_FALSE; goto done; } break; case AAA_AUTHORIZATION_REJECTED: LM_ERR("AAA_AUTHORIZATION_REJECTED returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_AUTHORIZATION_REJECTED); result = CSCF_RETURN_FALSE; goto done; case AAA_UNABLE_TO_COMPLY: LM_ERR("AAA_UNABLE_TO_COMPLY returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_UNABLE_TO_COMPLY); result = CSCF_RETURN_FALSE; goto done; case AAA_SUCCESS: goto success; default: LM_ERR("MSG_403_UNKOWN_RC returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_UNKOWN_RC); result = CSCF_RETURN_FALSE; goto done; } success: LM_DBG("successful UAA response\n"); list = I_get_capab_ordered(server_name, m_capab, m_capab_cnt, o_capab, o_capab_cnt, p_server_names, p_server_names_cnt, 0); if (!list) { LM_ERR("Empty capability list returning 600\n"); cscf_reply_transactional_async(t, t->uas.request, 600, MSG_600_EMPTY_LIST); result = CSCF_RETURN_FALSE; goto done; } if (!data->callid.len || !add_scscf_list(data->callid, list)) { LM_ERR("Error saving capability list 500\n"); cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_ERROR_SAVING_LIST); result = CSCF_RETURN_FALSE; goto done; } result = CSCF_RETURN_TRUE; done: //free capabilities if they exist if (m_capab) shm_free(m_capab); if (o_capab) shm_free(o_capab); if (p_server_names) shm_free(p_server_names); LM_DBG("DBG:UAR Async CDP callback: ... Done resuming transaction\n"); 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); create_uaa_return_code(result); if (t)tmb.unref_cell(t); //free memory if (uaa) cdpb.AAAFreeMessage(&uaa); tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_uar_transaction_data(data); return; error: if (t)tmb.unref_cell(t); //free memory if (uaa) cdpb.AAAFreeMessage(&uaa); tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_uar_transaction_data(data); }
void async_cdp_callback(int is_timeout, void *param, AAAMessage *maa, long elapsed_msecs) { int i, j; int rc = -1, experimental_rc = -1; saved_transaction_t* data = (saved_transaction_t*) param; struct cell *t = 0; int result = CSCF_RETURN_TRUE; int sip_number_auth_items; struct auth_data_item_list *adi_list = 0; AAA_AVP *auth_data; auth_data = 0; int item_number; str authenticate = {0, 0}, authorization2 = {0, 0}, ck = {0, 0}, ik = {0, 0}, ip = {0, 0}, ha1 = {0, 0}; str line_identifier = {0, 0}; str response_auth = {0, 0}, digest_realm = {0, 0}; auth_vector *av = 0, **avlist = 0; HASHHEX ha1_hex; HASHHEX result_hex; str etsi_nonce = {0, 0}; str private_identity, public_identity; str algorithm; if (is_timeout) { update_stat(stat_mar_timeouts, 1); LM_ERR("Transaction timeout - did not get MAA\n"); result = CSCF_RETURN_ERROR; goto error; } if (!maa) { LM_ERR("Error sending message via CDP\n"); result = CSCF_RETURN_ERROR; goto error; } update_stat(mar_replies_received, 1); update_stat(mar_replies_response_time, elapsed_msecs); if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); result = CSCF_RETURN_ERROR; goto error; } /* get the private_identity */ private_identity = get_private_identity(t->uas.request, data->realm, data->is_proxy_auth); if (!private_identity.len) { LM_ERR("No private identity specified (Authorization: username)\n"); stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_PRIVATE); result = CSCF_RETURN_FALSE; goto error; } /* get the public_identity */ public_identity = get_public_identity(t->uas.request); if (!public_identity.len) { LM_ERR("No public identity specified (To:)\n"); stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_PUBLIC); result = CSCF_RETURN_FALSE; goto error; } //get each individual element from the MAA cxdx_get_result_code(maa, &rc); cxdx_get_experimental_result_code(maa, &experimental_rc); cxdx_get_sip_number_auth_items(maa, &sip_number_auth_items); //now assign the auth_data_item elements //there can be many of these in the MAA struct auth_data_item *adi; int adi_len; char *p; while ((cxdx_get_auth_data_item_answer(maa, &auth_data, &item_number, &algorithm, &authenticate, &authorization2, &ck, &ik, &ip, &ha1, &response_auth, &digest_realm, &line_identifier))) { //create an auth_data_item for each entry in the MAA adi_len = sizeof (struct auth_data_item) +authenticate.len + authorization2.len + ck.len + ik.len + ip.len + ha1.len + line_identifier.len + response_auth.len + digest_realm.len + algorithm.len; adi = (struct auth_data_item*) shm_malloc(adi_len); if (!adi) { LM_CRIT("Out of memory!\n"); result = CSCF_RETURN_ERROR; goto done; } memset(adi, 0, adi_len); //put all elements in the auth_data_item entry p = (char*) (adi + 1); adi->authenticate.s = p; adi->authenticate.len = authenticate.len; memcpy(p, authenticate.s, authenticate.len); p += authenticate.len; adi->authorization.s = p; adi->authorization.len = authorization2.len; memcpy(p, authorization2.s, authorization2.len); p += authorization2.len; adi->auth_scheme.s = p; adi->auth_scheme.len = algorithm.len; memcpy(p, algorithm.s, algorithm.len); p += algorithm.len; adi->ck.s = p; adi->ck.len = ck.len; memcpy(p, ck.s, ck.len); p += ck.len; adi->ik.s = p; adi->ik.len = ik.len; memcpy(p, ik.s, ik.len); p += ik.len; adi->ip.s = p; adi->ip.len = ip.len; memcpy(p, ip.s, ip.len); p += ip.len; adi->ha1.s = p; adi->ha1.len = ha1.len; memcpy(p, ha1.s, ha1.len); p += ha1.len; adi->line_identifier.s = p; adi->line_identifier.len = line_identifier.len; memcpy(p, line_identifier.s, line_identifier.len); p += line_identifier.len; adi->response_auth.s = p; adi->response_auth.len = response_auth.len; memcpy(p, response_auth.s, response_auth.len); p += response_auth.len; adi->digest_realm.s = p; adi->digest_realm.len = digest_realm.len; memcpy(p, digest_realm.s, digest_realm.len); p += digest_realm.len; if (p != (((char*) adi) + adi_len)) { LM_CRIT("buffer overflow\n"); shm_free(adi); adi = 0; result = CSCF_RETURN_ERROR; goto done; } auth_data->code = -auth_data->code; adi->item_number = item_number; int len = sizeof (struct auth_data_item_list); adi_list = (struct auth_data_item_list*) shm_malloc(len); memset(adi_list, 0, len); if (adi_list->first == 0) { adi_list->first = adi_list->last = adi; } else { adi_list->last->next = adi; adi->previous = adi_list->last; adi_list->last = adi; } } if (!(rc) && !(experimental_rc)) { stateful_request_reply_async(t, t->uas.request, 480, MSG_480_DIAMETER_MISSING_AVP); result = CSCF_RETURN_FALSE; goto done; } switch (rc) { case -1: switch (experimental_rc) { case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN: stateful_request_reply_async(t, t->uas.request, 403, MSG_403_USER_UNKNOWN); result = CSCF_RETURN_FALSE; break; case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH: stateful_request_reply_async(t, t->uas.request, 403, MSG_403_IDENTITIES_DONT_MATCH); result = CSCF_RETURN_FALSE; break; case RC_IMS_DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED: stateful_request_reply_async(t, t->uas.request, 403, MSG_403_AUTH_SCHEME_UNSOPPORTED); result = CSCF_RETURN_FALSE; break; default: stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNKOWN_EXPERIMENTAL_RC); result = CSCF_RETURN_FALSE; } break; case AAA_UNABLE_TO_COMPLY: stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNABLE_TO_COMPLY); result = CSCF_RETURN_FALSE; break; case AAA_SUCCESS: goto success; break; default: stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNKOWN_RC); result = CSCF_RETURN_FALSE; } goto done; success: if (!sip_number_auth_items) { stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_AUTH_DATA); result = CSCF_RETURN_FALSE; goto done; } avlist = shm_malloc(sizeof (auth_vector *) * sip_number_auth_items); if (!avlist) { stateful_request_reply_async(t, t->uas.request, 403, MSG_480_HSS_ERROR); result = CSCF_RETURN_FALSE; goto done; } sip_number_auth_items = 0; struct auth_data_item *tmp; tmp = adi_list->first; while (tmp) { if (tmp->ip.len) av = new_auth_vector(tmp->item_number, tmp->auth_scheme, empty_s, tmp->ip, empty_s, empty_s); else if (tmp->line_identifier.len) av = new_auth_vector(tmp->item_number, tmp->auth_scheme, empty_s, line_identifier, empty_s, empty_s); else if (tmp->ha1.len) { if (tmp->response_auth.len) //HSS check { memset(ha1_hex, 0, HASHHEXLEN + 1); memcpy(ha1_hex, tmp->ha1.s, tmp->ha1.len > HASHHEXLEN ? 32 : tmp->ha1.len); etsi_nonce.len = tmp->authenticate.len / 2; etsi_nonce.s = pkg_malloc(etsi_nonce.len); if (!etsi_nonce.s) { LM_ERR("error allocating %d bytes\n", etsi_nonce.len); goto done; } etsi_nonce.len = base16_to_bin(tmp->authenticate.s, tmp->authenticate.len, etsi_nonce.s); calc_response(ha1_hex, &etsi_nonce, &empty_s, &empty_s, &empty_s, 0, &(t->uas.request->first_line.u.request.method), &scscf_name_str, 0, result_hex); pkg_free(etsi_nonce.s); if (!tmp->response_auth.len == 32 || strncasecmp(tmp->response_auth.s, result_hex, 32)) { LM_ERR("The HSS' Response-Auth is different from what we compute locally!\n" " BUT! If you sent an MAR with auth scheme unknown (HSS-Selected Authentication), this is normal.\n" "HA1=\t|%s|\nNonce=\t|%.*s|\nMethod=\t|%.*s|\nuri=\t|%.*s|\nxresHSS=\t|%.*s|\nxresSCSCF=\t|%s|\n", ha1_hex, tmp->authenticate.len, tmp->authenticate.s, t->uas.request->first_line.u.request.method.len, t->uas.request->first_line.u.request.method.s, scscf_name_str.len, scscf_name_str.s, tmp->response_auth.len, tmp->response_auth.s, result_hex); //stateful_register_reply(msg,514,MSG_514_HSS_AUTH_FAILURE); //goto done; } } av = new_auth_vector(tmp->item_number, tmp->auth_scheme, tmp->authenticate, tmp->ha1, empty_s, empty_s); } else av = new_auth_vector(tmp->item_number, tmp->auth_scheme, tmp->authenticate, tmp->authorization, tmp->ck, tmp->ik); if (sip_number_auth_items == 0) avlist[sip_number_auth_items++] = av; else { i = sip_number_auth_items; while (i > 0 && avlist[i - 1]->item_number > av->item_number) i--; for (j = sip_number_auth_items; j > i; j--) avlist[j] = avlist[j - 1]; avlist[i] = av; sip_number_auth_items++; } //TODO need to confirm that removing this has done no problems //tmp->auth_data->code = -tmp->auth_data->code; LM_DBG("Added new auth-vector.\n"); tmp = tmp->next; } //MAA returns a whole list of av! Which should we use? //right now we take the first and put the rest in the AV queue //then we use the first one and then add it to the queue as sent! for (i = 1; i < sip_number_auth_items; i++) if (!add_auth_vector(private_identity, public_identity, avlist[i])) free_auth_vector(avlist[i]); if (!pack_challenge(t->uas.request, data->realm, avlist[0], data->is_proxy_auth)) { stateful_request_reply_async(t, t->uas.request, 500, MSG_500_PACK_AV); result = CSCF_RETURN_FALSE; goto done; } if (data->is_proxy_auth) stateful_request_reply_async(t, t->uas.request, 407, MSG_407_CHALLENGE); else stateful_request_reply_async(t, t->uas.request, 401, MSG_401_CHALLENGE); done: if (avlist) { start_reg_await_timer(avlist[0]); //start the timer to remove stale or unused Auth Vectors //now we add it to the queue as sent as we have already sent the challenge and used it and set the status to SENT if (!add_auth_vector(private_identity, public_identity, avlist[0])) free_auth_vector(avlist[0]); } //free memory if (maa) cdpb.AAAFreeMessage(&maa); if (avlist) { shm_free(avlist); avlist = 0; } if (adi_list) { struct auth_data_item *tmp1 = adi_list->first; while (tmp1) { struct auth_data_item *tmp2 = tmp1->next; shm_free(tmp1); tmp1 = tmp2; } shm_free(adi_list); adi_list = 0; } LM_DBG("DBG:UAR Async CDP callback: ... Done resuming transaction\n"); 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); //make sure we delete any private lumps we created create_return_code(result); 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; error: //don't need to set result code as by default it is ERROR! 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); }
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; struct sip_msg* req; 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 and t is now pointing to %p and will be set to NULL\n", t); t = NULL; 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(); req = get_request_from_tx(t); if (!req) { LM_ERR("Failed to get SIP Request from Transaction\n"); goto error_no_send; } 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(req) < 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 (s) { if (build_p_associated_uri(s) != 0) { LM_ERR("Unable to build p_associated_uri\n"); rerrno = R_SAR_FAILED; goto error; } } } if (s) { //here we update the contacts and also build the new contact header for the 200 OK reply if (update_contacts(req, 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(req, 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(&req->reply_lump); tmb.unref_cell(t); } //free path vector pkg memory // reset_path_vector(req); 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(req, 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(&req->reply_lump); tmb.unref_cell(t); } tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_transaction_data(data); return; }