From 18410da04c7f7bbc9628820427fedb92cf893526 Mon Sep 17 00:00:00 2001 From: Theo Date: Fri, 17 Apr 2020 08:53:00 +0000 Subject: [PATCH] tm: 200 OK not processed correctly by Proxy after final non-2xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description: Problem: Forwarding of 200 OK while sent 488 waits for ACK, destroys the UAS send buffer Scenario: During suspension of 200 OK by ims_qos module function Rx_AAR() at terminating PCSCF, The PCRF sends an AA Answer with result code DIAMETER_TOO_BUSY (3004), which triggers the PCSCF to send a 488 ‘Sorry no QoS available’ to the originating side (ims_dialog module function dlg_terminate()). Afterwards neither the 200 OK nor the ACK(488) is processed correctly by the PCSCF. Solution: The UAS send buffer should not be overwritten during processing of 200 OK, because non-2xx is needed to associate the ACK message in a correct way. 200 OK must be forwarded statelessly. Side-Effect (potentially breaks existing function): Some callbacks cannot be called for the 200 OK, to avoid messing the stored 488. --- src/modules/tm/t_reply.c | 72 +++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/modules/tm/t_reply.c b/src/modules/tm/t_reply.c index 51b669f776e..dcf4537f08f 100644 --- a/src/modules/tm/t_reply.c +++ b/src/modules/tm/t_reply.c @@ -2042,40 +2042,42 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, goto error02; } - /* attempt to copy the message to UAS's shmem: - * - copy to-tag for ACK matching as well - * - allocate little a bit more for provisional as - * larger messages are likely to follow and we will be - * able to reuse the memory frag - */ - if (res_len<=0) { - LM_ERR("invalid new buffer len\n"); - goto error03; - } - uas_rb->buffer = (char*)shm_resize( uas_rb->buffer, res_len + - (msg_status<200 ? REPLY_OVERBUFFER_LEN : 0)); - if (!uas_rb->buffer) { - LM_ERR("cannot alloc reply shmem\n"); - goto error03; - } - uas_rb->rbtype = relayed_code; - uas_rb->buffer_len = res_len; - memcpy( uas_rb->buffer, buf, res_len ); - if (relayed_msg==FAKED_REPLY) { /* to-tags for local replies */ - update_local_tags(t, &bm, uas_rb->buffer, buf); - t_stats_rpl_generated(); - } + if (reply_status != RPS_PUSHED_AFTER_COMPLETION) { + /* attempt to copy the message to UAS's shmem: + * - copy to-tag for ACK matching as well + * - allocate little a bit more for provisional as + * larger messages are likely to follow and we will be + * able to reuse the memory frag + */ + if (res_len<=0) { + LM_ERR("invalid new buffer len\n"); + goto error03; + } + uas_rb->buffer = (char*)shm_resize( uas_rb->buffer, res_len + + (msg_status<200 ? REPLY_OVERBUFFER_LEN : 0)); + if (!uas_rb->buffer) { + LM_ERR("cannot alloc reply shmem\n"); + goto error03; + } + uas_rb->rbtype = relayed_code; + uas_rb->buffer_len = res_len; + memcpy( uas_rb->buffer, buf, res_len ); + if (relayed_msg==FAKED_REPLY) { /* to-tags for local replies */ + update_local_tags(t, &bm, uas_rb->buffer, buf); + t_stats_rpl_generated(); + } - /* update the status ... */ - t->uas.status = relayed_code; - t->relayed_reply_branch = relay; + /* update the status ... */ + t->uas.status = relayed_code; + t->relayed_reply_branch = relay; - if ( unlikely(is_invite(t) && relayed_msg!=FAKED_REPLY - && relayed_code>=200 && relayed_code < 300 - && has_tran_tmcbs( t, - TMCB_RESPONSE_OUT|TMCB_RESPONSE_READY - |TMCB_E2EACK_IN|TMCB_E2EACK_RETR_IN))) { - totag_retr=update_totag_set(t, relayed_msg); + if ( unlikely(is_invite(t) && relayed_msg!=FAKED_REPLY + && relayed_code>=200 && relayed_code < 300 + && has_tran_tmcbs( t, + TMCB_RESPONSE_OUT|TMCB_RESPONSE_READY + |TMCB_E2EACK_IN|TMCB_E2EACK_RETR_IN))) { + totag_retr=update_totag_set(t, relayed_msg); + } } } /* if relay ... */ @@ -2100,7 +2102,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, } if (likely(uas_rb->dst.send_sock)) { if (onsend_route_enabled(SIP_REPLY) && p_msg - && (p_msg != FAKED_REPLY)) { + && (p_msg != FAKED_REPLY) && (reply_status != RPS_PUSHED_AFTER_COMPLETION)) { if (run_onsend(p_msg, &uas_rb->dst, buf, res_len)==0){ su2ip_addr(&ip, &(uas_rb->dst.to)); LM_ERR("reply to %s:%d(%d) dropped" @@ -2116,7 +2118,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, if (SEND_PR_BUFFER( uas_rb, buf, res_len ) >= 0){ LM_DBG("reply buffer sent out\n"); if (unlikely(!totag_retr - && has_tran_tmcbs(t, TMCB_RESPONSE_OUT))){ + && has_tran_tmcbs(t, TMCB_RESPONSE_OUT) && (reply_status != RPS_PUSHED_AFTER_COMPLETION))){ LOCK_REPLIES( t ); if(relayed_code==uas_rb->rbtype) { run_trans_callbacks_with_buf( TMCB_RESPONSE_OUT, uas_rb, @@ -2128,7 +2130,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, } UNLOCK_REPLIES( t ); } - if (unlikely(has_tran_tmcbs(t, TMCB_RESPONSE_SENT))){ + if (unlikely(has_tran_tmcbs(t, TMCB_RESPONSE_SENT) && (reply_status != RPS_PUSHED_AFTER_COMPLETION))){ INIT_TMCB_ONSEND_PARAMS(onsend_params, t->uas.request, relayed_msg, uas_rb, &uas_rb->dst, buf, res_len,