Repository navigation
Nethvoice: Support inbound DID extraction from SIP header P-Preferred-Identity #8179
Description
Description
Some SIP providers use the P-Preferred-Identity header to carry the called number (DID) on incoming calls when the trunk is configured as a multi-number trunk.
In this scenario, the number normally used by NethVoice through the Asterisk configuration files to identify the inbound route does not allow the different DIDs associated with the same trunk to be distinguished.
For example, the provider sends an incoming INVITE containing:
P-Preferred-Identity: <sip:0123456789@provider.example>
where 0123456789 represents the DID that was called.
As a consequence, different inbound routes cannot be configured according to the number dialed by the caller.
Current behavior
At the moment this behavior can be implemented by manually adding a custom dialplan context to Asterisk's extensions_custom.conf.
The purpose of this feature is to include the required dialplan logic directly in the Asterisk configuration files provided by NethVoice, making the following context available by default:
from-pstn-preferredin
The administrator can then simply configure the trunk to use from-pstn-preferredin as its inbound context.
This avoids having to manually add and maintain the same custom dialplan code in extensions_custom.conf on every installation where a provider uses P-Preferred-Identity to transport the called DID.
The expected workflow would therefore be:
SIP trunk
|
| context = from-pstn-preferredin
v
[from-pstn-preferredin]
|
| extract DID from P-Preferred-Identity
v
[from-pstn]
|
v
standard inbound routing
Adding this context to the Asterisk configuration files provided by NethVoice makes the configuration reproducible and managed by the product, instead of relying on installation-specific changes to extensions_custom.conf.
Proposed solution
Add the from-pstn-preferredin dialplan context to the Asterisk configuration files provided by NethVoice.
When a trunk is configured with:
context=from-pstn-preferredin
the context should:
- Read the
P-Preferred-Identityheader from the incoming SIP INVITE. - Extract the user/number part from the SIP URI.
- Use the extracted number as the DID.
- Forward the call to the standard
from-pstncontext. - Fall back to the original called extension if the channel type cannot be handled.
The feature remains explicitly enabled on a per-trunk basis simply by selecting from-pstn-preferredin as the trunk context.
Current workaround
The following custom dialplan is currently added manually to extensions_custom.conf:
[from-pstn-preferredin]
exten => _.,1,NoOp(Attempting to extract DID from SIP P-Preferred-Identity header)
exten => _.,n,GotoIf($["${CHANNEL(channeltype)}"="SIP"]?SIP)
exten => _.,n,GotoIf($["${CHANNEL(channeltype)}"="PJSIP"]?PJSIP)
exten => _.,n,NoOp(Unable to determine SIP channel type)
exten => _.,n,Goto(from-pstn,${EXTEN},1)
exten => _.,n(SIP),Goto(from-pstn,${CUT(CUT(SIP_HEADER(P-Preferred-Identity),@,1),:,2)},1)
exten => _.,n(PJSIP),Goto(from-pstn,${CUT(CUT(PJSIP_HEADER(read,P-Preferred-Identity),@,1),:,2)},1)
Once this context is included in the Asterisk configuration files provided by NethVoice, the administrator would only need to configure the incoming trunk with:
context=from-pstn-preferredin
without adding any custom dialplan to extensions_custom.conf.
Expected behavior
Given an incoming INVITE containing:
P-Preferred-Identity: <sip:0123456789@provider.example>
and a trunk configured with:
context=from-pstn-preferredin
the dialplan included in the Asterisk configuration files provided by NethVoice should extract:
0123456789
and continue the call through:
from-pstn,0123456789,1
allowing the standard inbound routing mechanism to differentiate the individual numbers belonging to the same multi-number trunk.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTesting
Activity
edospadoni commentedon Oct 27, 2026
Test
PR: nethesis/ns8-nethvoice#1115
Setup: a NethVoice instance with a PJSIP trunk whose provider delivers the called DID in the
P-Preferred-Identityheader (multi-number trunk), i.e. an INVITE carryingP-Preferred-Identity: <sip:0123456789@provider.example>with the same Request-URI number for every DID. If no such provider is available, an INVITE with that header can be injected withsipptowards the trunk (through nethvoice-proxy when the instance is behind it). If the[from-pstn-preferredin]workaround was added by hand toextensions_custom.conf, remove it after the update, otherwise Asterisk logs duplicate priority warnings on that context at every reload.Asterisk CLI on NS8:
runagent -m nethvoiceX podman exec freepbx asterisk -rx "<command>".Test Case 1 - Context generated
asterisk -rx "dialplan show from-pstn-preferredin"shows the context with five priorities:NoOp,GotoIfon the channel type,Set(PPI_DID=...),GotoIfon emptyPPI_DID,Goto(from-pstn,${PPI_DID},1)from-pstn-preferredinas context (Connectivity > Trunks > trunk > PJSIP Settings > Advanced > Context) and the configuration applies without errorsTest Case 2 - DID taken from P-Preferred-Identity
from-pstn-preferredinand create two inbound routes for two DIDs of the trunk with different destinationsGoto(from-pstn,<DID1>,1)with the number carried by the headerTest Case 3 - Fallback and regression
P-Preferred-Identityon the same trunk (e.g. withsipp) is routed byfrom-pstnwith the number of the Request-URI, the call is not droppedfrom-pstn-toheader/from-pstn-identity) keep working as before, inbound and outboundTest Case 4 - Behind nethvoice-proxy (when available)
Testing image (built from nethesis/ns8-nethvoice#1115, not merged yet):
Update command (replace
nethvoiceXwith the NethVoice instance):cc @margit86