Skip to content

sipreg: add Contact rewrite from Via received/rport - #1628

Open
qfiber wants to merge 2 commits into
baresip:mainfrom
qfiber:sipreg-contact-rewrite
Open

qfiber wants to merge 2 commits into
baresip:mainfrom
qfiber:sipreg-contact-rewrite

Conversation

@qfiber

@qfiber qfiber commented Oct 3, 2026 •

Copy link
Copy Markdown

Behind a NAT the local address in the REGISTER Contact is not reachable from the registrar. Registrars that rewrite the Contact from the request's source hide this; with the rest, requests to the registered contact never arrive.

This adds an opt-in Contact rewrite to sipreg, based on the address the registrar reports in the received and rport parameters of the 2xx's top Via (RFC 3261 18.2.1, RFC 3581):

  • sipreg_set_contact_rewrite(reg, true) enables it (off by default, so nothing changes for existing users).
  • When a 2xx shows an address that differs from the one in our Contact, the client sends a new REGISTER with that address, and removes the stale binding with a second Contact: ...;expires=0 in the same request.
  • The response handler is only called for the final response, so the application sees one successful registration.
  • Two addresses taking turns (multiple NAT mappings) are capped at two consecutive rewrites.
  • sipreg_contact_addr() returns the address currently in the Contact (the learned one when rewritten, otherwise laddr), so an application can use it in the Contact of its dialogs as well. A baresip PR using this follows.

The test puts the mock NAT (NAT_INBOUND_SNAT) on the mock registrar's UDP socket (via the new sip_transp_udp_sock()), so the registrar sees the client at 192.0.2.10, and checks the second REGISTER: the stale local binding with expires=0, then the public one. It fails without the rewrite enabled. retest -r passes, also under ASan, and ccheck is clean.

Tested against Asterisk 22 behind a home NAT: the client registers its private address, re-registers with the public one and removes the private binding.

Behind a NAT the local address in the REGISTER Contact is not reachable
from the registrar, so requests to the registered contact never arrive
unless the server rewrites the Contact itself.

sipreg_set_contact_rewrite() makes the client register the address the
registrar reports in the received and rport parameters of the 2xx's top
Via (RFC 3261 18.2.1, RFC 3581): when it differs from the address in the
Contact, the client sends a new REGISTER with that address and removes
the stale binding (expires=0) in the same request. Two addresses taking
turns are capped at two consecutive rewrites. sipreg_contact_addr()
returns the address currently in the Contact, so an application can use
it for its dialogs too. Off by default.

The test puts the mock NAT in front of the mock registrar and checks the
second REGISTER.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qfiber
qfiber force-pushed the sipreg-contact-rewrite branch from b8eaf15 to 96f2857 Compare October 3, 2026 08:26
qfiber added a commit to qfiber/baresip that referenced this pull request Oct 3, 2026
Behind a NAT the local address in the Contact is not reachable from the
registrar. Registrars that rewrite the Contact from the request's source
(Asterisk rewrite_contact, Kamailio fix_nated_register, SBCs) hide this;
the rest can never send the client a request.

With sipnat=rport the registration uses re's Contact rewrite
(sipreg_set_contact_rewrite()): it registers the address the registrar
reports in the received and rport parameters of its responses. The UA
then uses that address in the Contact of its dialogs as well
(ua_cuser(), after a public GRUU), so in-dialog requests from the far
end reach it too.

Needs baresip/re#1628 (sipreg_set_contact_rewrite, sipreg_contact_addr).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
qfiber added a commit to qfiber/baresip that referenced this pull request Oct 5, 2026
Comment thread src/sipreg/reg.c Outdated
Comment thread src/sipreg/reg.c Outdated
Comment thread src/sipreg/reg.c Outdated
Comment thread src/sipreg/reg.c Outdated
Comment thread test/sipreg.c Outdated
Rename contact_rewrite() to rewrite_contact(), drop the comments on the
static helpers, cite RFC 3261 18.2.1 and RFC 3581 in the API doc of
sipreg_set_contact_rewrite(), and use doxygen style for the test's comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qfiber

qfiber commented Oct 10, 2026

Copy link
Copy Markdown
Author

Thanks for the review, and sorry for the extra work. I'm new to contributing here, so apologies for the mistakes.

All done in 7e4fd4c: renamed to rewrite_contact(), removed the comments on the static helpers, added the RFC sections to the sipreg_set_contact_rewrite() doxygen, and switched the test comment to doxygen style.

@cspiel1
cspiel1 requested review from cspiel1 and sreimers October 10, 2026 14:36

@cspiel1 cspiel1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants