15 March 2011

SIP Loop Detection - Part 1: RFC3261 Summary

This post is a short summary based on RFC3261. The goal of this post is to filter RFC content relevant to loop detection prior detailed investigation of looped call behaviour on Cisco gateways.

There are two kinds of "looped" calls described in RFC3261: spiral and loop.
Spiral is not an error. A typical example is call forwarding. Look at the picture, the call was forwarded to bob@example.com. Changed request content (typically, changed Request-URI) is the most important distinguisher of a spiral. The result is different processing decision than the original request.
.                          |=======|                           |=======|
  INVITE joe@example.com   |       |  INVITE joe@example.com   |       |
 ------------------------> | Proxy | ------------------------> |Proxy 2| --|
  INVITE bob@example.com   |       |                           |       |   |
 |-----------------------> |=======|                           |=======|   |
 |                                                                         |
 |-------------------------------------------------------------------------|
Loop is an error. A request that arrives, is forwarded and later comes back. Request-URI and other header fields that affects proxy operation are unchanged, processing decision would be the same. SIP relies on special procedures for loop detection and handling.

The first thing we have to mention is Via header. It indicates the transport used for the transaction and identifies the location where the response is to be sent. Here is an example:
Via: SIP/2.0/UDP 192.168.192.2:5060;branch=z9hG4bK1E1AF6
The Via header field value MUST contain a branch parameter. This parameter is used to identify the transaction created by that request. The branch parameter value MUST be unique across space and time for all requests sent by the UA. The exception to this rule are CANCEL and ACK for non-2xx responses.
The branch ID must always begin with magic cookie "z9hG4bK" to indicate RFC3261 compliance (older RFC2543 implementation would not pick such a value). Beyond this requirement, the precise format of the branch token is implementation-defined.

When a request is received, it has to be matched to an existing transaction. If branch parameter is present and begins with the magic cookie "z9hG4bK", the request was generated by a client transaction compliant to RFC3261. Therefore, the branch parameter will be unique across all transactions sent by that client. The request matches a transaction if:
1) the branch parameter in the request is equal to the one in the top Via header field of the request that created the transaction, and
2) the sent-by value in the top Via of the request is equal to the one in the request that created the transaction, and
3) the method of the request matches the one that created the transaction, except for ACK, where the method of the request that created the transaction is INVITE.

Here is sample debug from Cisco router (some output omitted):
INVITE sip:101@192.168.254.254:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.192.2:5060;branch=z9hG4bK38263F
Remote-Party-ID: "FXS-201" ;party=calling;screen=no;privacy=off
From: "FXS-201" ;tag=205C26A8-419
To: 
Date: Tue, 15 Mar 2011 14:57:42 GMT
Call-ID: 698D707B-4E4B11E0-81B7B37D-1C03072D@192.168.192.2
Supported: 100rel,timer,resource-priority,replaces
Min-SE:  1800
Cisco-Guid: 1744876936-1313542624-2175972221-469960493
User-Agent: Cisco-SIPGateway/IOS-12.x
Allow: INVITE, OPTIONS, BYE, CANCEL, ACK, PRACK, UPDATE, REFER, SUBSCRIBE, NOTIFY, INFO, REGISTER
CSeq: 101 INVITE
Max-Forwards: 70
Timestamp: 1300201062
Contact: 
Expires: 180
Allow-Events: telephone-event
Content-Type: application/sdp
Content-Disposition: session;handling=required
Content-Length: 241
...
Received:
CANCEL sip:101@192.168.254.254:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.192.2:5060;branch=z9hG4bK38263F
From: "FXS-201" ;tag=205C26A8-419
To: 
Date: Tue, 15 Mar 2011 14:57:42 GMT
Call-ID: 698D707B-4E4B11E0-81B7B37D-1C03072D@192.168.192.2
CSeq: 101 CANCEL
Max-Forwards: 70
Timestamp: 1300201065
Reason: Q.850;cause=16
Content-Length: 0
Looks very RFC friendly.

Loop detection check is optional. It is performed by verifying that, when a request returns to a proxy, those fields having impact in the processing of the request have not changed. The value placed in this part of the branch parameter SHOULD reflect all of those fields (including any Route, Proxy-Require and Proxy-Authorization header fields). A common way to create this value is to compute a cryptographic hash of the To tag, From tag, Call-ID header field, the Request-URI of the request received (before translation), the topmost Via header, and the sequence number from the CSeq header field, in addition to any Proxy-Require and Proxy-Authorization header fields that may be present. The algorithm used to compute the hash is implementation-dependent, but MD5 (RFC 1321), expressed in hexadecimal, is a reasonable choice.

The Max-Forwards header should be inserted by elements that can not otherwise guarantee loop detection. This header limits the number of proxies or gateways that can forward the request to the next downstream server. The recommended initial value is 70. It is decremented by each server that forwards the request.

That's an RFC point of view. Now it's time to check.

To be continued...

No comments:

Post a Comment