[Home]

Summary:ASTERISK-24915: [patch]Missing Contact: header in 200 OK
Reporter:Etienne Allovon (etienne_pf)Labels:patch
Date Opened:2015-03-26 08:22:56Date Closed:
Priority:MajorRegression?
Status:Open/NewComponents:Channels/chan_sip/General
Versions:1.8.32.2 11.16.0 13.18.4 Frequency of
Occurrence
Frequent
Related
Issues:
is related toASTERISK-17258 missing Contact header in 200 OK to INVITE
is related toASTERISK-25031 DTMF INFO before answer leads to 200 OK without Contact: header
Environment:Attachments:( 0) AST-24915.diff
( 1) ASTERISK-24915.pcapng
( 2) ASTERISK-24915-asterisk-extensions.conf
( 3) ASTERISK-24915-asterisk-full.log
( 4) ASTERISK-24915-asterisk-sip.conf
( 5) REGISTER_INVITE_client.csv
( 6) REGISTER_INVITE_client.xml
Description:*Summary*

In some cases asterisk answers a call (SIP 200 OK) without the {{Contact:}} header.
It results, for the receiving peer, to terminate the call (SIP BYE) because he can't answer.
For example, if the receiving peer is an asterisk, you get the following WARNING in the CLI :
{code}
WARNING[32089] chan_sip.c: Invalid contact uri  (missing sip: or sips:), attempting to use anyway
{code}

More precisely this happens when asterisk receives a SIP message with a bad CSeq (for example with CSeq-1). Then the next 200 OK doesn't contain the Contact: header.

*When does it happen in real life ?*

In real life I saw it with two asterisk interconnected with a SIP trunk via a WAN.
When there is some asymetric latency it results in retransmissions.
{code}
< INVITE            (CSeq 1)
> 401 Unauthorized  (CSeq 1)
> 401 Unauthorized  (CSeq 1) .... retransmission because ACK is not received on time
< ACK               (CSeq 1) .... ACK of the first 401 Unauthorized
< INVITE            (CSeq 2)
> 100 Trying        (CSeq 2)  
> 180 Ringing       (CSeq 2)
< ACK               (Cseq *1*) .. ACK of the retransmitted 401 Unauthorized
> 200 OK            (Cseq 2) .... /!\ which does not contain the Contact: header
{code}


*How to reproduce*
Below is a SIP exchange forged with SIPp which reproduce the problem :

{code}
< INVITE            (CSeq 1)
> 401 Unauthorized  (CSeq 1)
< ACK               (CSeq 1)
< INVITE            (CSeq 2)
> 100 Trying        (CSeq 2) ..... contains Contact: header
> 180 Ringing       (CSeq 2) ..... contains Contact: header
< ACK               (Cseq *1*)
> 200 OK            (Cseq 2) ..... /!\ does not contain Contact: header
{code}

The bug appears at step #7.
Asterisk seems to handle the spurious ACK correctly since you find the following DEBUG message :
{code}
DEBUG[26739] chan_sip.c: **** Received ACK (6) - Command in SIP ACK
DEBUG[26739] chan_sip.c: Ignoring too old SIP packet packet 1 (expecting >= 2)
DEBUG[26739] chan_sip.c: SIP message could not be handled, bad request: 261113e445fb3f8777068f5513a8d61f@10.14.12.1:5060
{code}

Here's the SIPp command to launch the scenario :
{code}
/usr/src/sipp-3.3/sipp 192.168.18.55 -sf REGISTER_INVITE_client.xml -inf REGISTER_INVITE_client.csv -i 192.168.18.11 -m 1 -l 1 -r 1
{code}

You need to :

* replace 192.168.18.65 asterisk IP,
* replace 192.168.18.11 with SIPp client IP
* get the REGISTER_INVITE_client.xml file,
* get the REGISTER_INVITE_client.csv file and change the authentication information


*References*
SIPp scenarios based on examples found here : http://tomeko.net/other/sipp/sipp_cheatsheet.php?lang
Comments:By: Etienne Allovon (etienne_pf) 2015-03-26 08:26:29.486-0500

SIPp scenario and configuration file

By: Rusty Newton (rnewton) 2015-03-26 17:58:20.289-0500

Thanks for the detailed and thorough report!

In case we run into issues in reproduction, would you also be able to attach a pcap of the issue playing out, along with the Asterisk logs (with 'DEBUG' logger channel on and turned up to 5).

After this, remember to hit Send Back or Enter Feedback so we'll see the issue. Thanks again!


By: Etienne Allovon (etienne_pf) 2015-03-27 03:26:38.964-0500

Update sipp configuration file and add a sip.conf and extensions.conf to reproduce the problem.

By: Etienne Allovon (etienne_pf) 2015-03-27 03:44:37.383-0500

I ran the sipp scenario against asterisk 11.16.0
Attached, are the log full and .pcap trace associated.

By: Etienne Allovon (etienne_pf) 2015-03-27 03:47:22.267-0500

I ran the sipp scenario against an asterisk 11.16.0.
I attached :
* the asterisk full log (with {{sip set debug on}} and {{core set debug 5 chan_sip}})
* the pcap trace ({{tshark 'port 5060'}})

Plus, I added a {{sip.conf}} and {{extensions.conf}} and changed the sipp configuration file accordingly (sip credentials and extension to call).


By: Rusty Newton (rnewton) 2015-03-31 15:59:11.385-0500

Thanks!

By: Etienne Lessard (hexanol) 2015-04-20 14:45:48.326-0500

I've taken a look at the bug in asterisk 11, and the problem comes from the handle_incoming function:

{code}
...
p->method = req->method; /* Find out which SIP method they are using */
ast_debug(4, "**** Received %s (%u) - Command in SIP %s\n", sip_methods[p->method].text, sip_methods[p->method].id, cmd);

if (p->icseq && (p->icseq > seqno) ) {
if (p->pendinginvite && seqno == p->pendinginvite && (req->method == SIP_ACK || req->method == SIP_CANCEL)) {
ast_debug(2, "Got CANCEL or ACK on INVITE with transactions in between.\n");
} else {
ast_debug(1, "Ignoring too old SIP packet packet %u (expecting >= %u)\n", seqno, p->icseq);
if (req->method == SIP_INVITE) {
unsigned int ran = (ast_random() % 10) + 1;
char seconds[4];
snprintf(seconds, sizeof(seconds), "%u", ran);
transmit_response_with_retry_after(p, "500 Server error", req, seconds); /* respond according to RFC 3261 14.2 with Retry-After betwewn 0 and 10 */
} else if (req->method != SIP_ACK) {
transmit_response(p, "500 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */
}
return -1;
}
} ...
{code}

The problem occurs because the handle_incoming function updates p->method to req->method (p being a struct sip_pvt *) before checking if the CSeq makes sense, and if the CSeq is unexpected, it does not reset p->method to its old value before returning. Then, when asterisk sends the 200 OK response for the original INVITE, since p->method is now equal to SIP_ACK (instead of SIP_INVITE), the resp_need_contact function (called from respprep) says "its a SIP ACK, no need to add a Contact header for the response", which is wrong, since it's not a SIP ACK but a SIP INVITE dialog.

I've attached a "quick and dirty" patch that fix the scenario described in this ticket. That said, I would not be surprised if a more "complete" patch would be required to fix a more global problem; the problem being that p->method might not always be in the right state after the handle_incoming function returns.

Note that I'm not a chan_sip expert.

By: Etienne Allovon (etienne_pf) 2015-04-29 07:11:30.211-0500

Hi,

Many thanks to my homonym for this little patch :)

I tested it and it works great. At least it fixes the above scenario.

Any news from your side, Rusty ? Any chance you may test this patch ?

By: Rusty Newton (rnewton) 2015-04-30 19:09:01.420-0500

Etienne, thanks for your work. I'm not a developer - I mostly marshal things along and perform some basic triage.

As far as the patch goes, you should follow the [Patch Contribution Process|https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process] and get it up on Gerrit where others can test and review it..

Thanks!

By: Tim Bowyer (timbo) 2016-08-17 21:05:28.766-0500

Hi All,
Confirmed this issue still exists on 11.23.0 due to end-user client complaint and also confirmed via above posted sipp scenario.
Applied patch to 11.23.0 - problem resolved.
I'm surprised a fairly critical bug such as this hasn't had more attention?  Will the fix be moved to source?

Cheers,

Tim

By: Joshua C. Colp (jcolp) 2016-08-18 05:42:38.888-0500

All contributions to Asterisk go through code review using Gerrit. Since the individual who created the attached patch did not do so it falls to someone else to do so and take it through the process, that has not yet happened.

By: Trevor Hemsley (themsley) 2022-12-16 08:39:24.672-0600

Sorry to resurrect an apparently long dead issue but this appears to still not be patched and I wonder what needs to be done to get it so? I would be quite happy to go through the patch contribution process but I'm not sure if that's allowed since it's not my patch. The patch is a single line and appears sane from my quick read of the code though as above, I am also not a chan_sip expert...