Hi,
Found an interesting call-flow today where a client (pjsip) is behind NAT and behaves like this during registration (kamailio-3.1.3):
REGISTER sip:somedomain.com Contact: sip:me@10.0.0.7:2001;ob Expires: 900
SIP/2.0 200 OK Contact: sip:me@10.0.0.7:2001;ob;expires=900;received="sip:1.2.3.4:3001"
REGISTER sip:somedomain.com Contact: sip:me@1.2.3.4:3001;transport=UDP;ob Contact: sip:me@10.0.0.7:2001;ob;expires=0 Expires: 900
SIP/2.0 200 OK Contact: sip:me@10.0.0.7:2001;ob;expires=900;received="sip:1.2.3.4:3001", sip:me@1.2.3.4:3001;transport=UDP;ob;expires=900
So obviously the client is trying to unregister its private contact (for whatever reason - probably to play nice with registrars not supporting far-end NAT traversal), and tries to register the Contact with the "received" address instead. Kamailio however ignores the ";expires=0" for the private Contact and just saves both of them with the expiry value given in the Expires header.
Taking the client behavior aside for now: is this the correct behavior of the registrar module? In RFC3261 chapter 10.2.1.1 it says:
#+ There are two ways in which a client can suggest an expiration interval for a binding: through an Expires header field or an "expires" Contact header parameter. The latter allows expiration intervals to be suggested on a per-binding basis when more than one binding is given in a single REGISTER request, whereas the former suggests an expiration interval for all Contact header field values that do not contain the "expires" parameter. #-
So I'd say that in my specific case "expires" Contact header param (which is 0 for the binding having 10.0.0.7) should de-register this particular binding, whereas the Expires header should be applied to the second binding (having the 1.2.3.4) because it doesn't carry an "expires" param.
Opinions on that one?
Andreas