How to use a custom SIP header to pass the DID (or other data) between two Asterisk servers that jointly handle extensions

NOTE: This post has been edited to show a newer method that should work with both PJSIP and Chan_SIP trunks.

If you have multiple Asterisk or FreePBX servers at different locations that pass Intra-Company traffic between each other using SIP trunks, you may have wished for a way to pass the Calling DID number (or some other bit of data stored in an Asterisk variable) from one server to another. For example, let’s suppose that all extensions in your company are four digits in length, and that the extensions on server A are numbered 1000-1099, and on server B they are numbered 1100-1199, and when a call comes in on system A that goes to an extension on system B, you want to pass the original DID that the call arrived on to system B so that it will be included in the call detail for that call.  It’s easy to do this; I’ll first show what you’d need to do on a server A that is running FreePBX.

In /etc/asterisk/extensions_custom.conf, you should find a context named [macro-dialout-trunk-predial-hook], and if you’ve not previously modified it then you should only need to add these four lines to that context (the last two of which may already be present):

exten => s,1,Set(regx=^11[0-9]{2}$)
exten => s,n,ExecIf($[${REGEX("${regx}" ${OUTNUM})} = 1]?Set(HASH(__SIPHEADERS,X-DID)=${CDR(did)}))
exten => s,n,MacroExit()
exten => h,1,Macro(hangupcall,)

The above has been modified to show the new way to do this in more recent versions of FreePBX. It is the only way that will work (without adding a lot more dialplan) if you are using a PJSIP trunk. If you are curious as to why this works, it turns out that in recent FreePBX versions, at the time the Asterisk Dial statement is executed a context named func-apply-sipheaders is executed, and the purpose of the context is to create additional SIP headers that have been set using a statement similar to the one we have used here. So, that works out rather well for our intended usage.

The previous method was to use this line as the second line of the context, which may still work for Chan SIP trunks:

exten => s,n,ExecIf($[${REGEX("${regx}" ${OUTNUM})} = 1]?SIPAddHeader(X-DID: ${CDR(did)}))

Anyway, to explain the context above, the first line sets a regular expression to match the digits 11XX – if you also do this on server B you would of course change the 11 to 10. There is probably a way to do this without using a regular expression but I just wanted to show this method because if offers the most flexibility in matching numbers (although Asterisk has a somewhat unique way of implementing regular expressions; that’s why I have to use [0-9] rather than d to indicate “any digit” in the expression). In the second line, if the regular expression matches the called number (the destination extension), the statement Set(HASH(__SIPHEADERS,X-DID)=${CDR(did)}) (formerly SIPAddHeader(X-DID: ${CDR(did)}) ) is executed, which takes the contents of the CDR(did) variable and puts it into a custom SIP header named X-DID, which follows the standard convention of adding X- to the start of a user-created SIP header. This is then transmitted to server B as part of the first INVITE message in the channel. In raw Asterisk (no FreePBX), you just need to make sure that something similar to the statements in the first two lines come before whatever statement sends the call to the other system (usually a Dial statement of some kind).

Now when the call comes into server B, we need a way to do the opposite, which is to get the content of the X-DID SIP header and place it into the CDR(did) variable.  So in the trunk, instead of making the context=from-internal, we can make it something like context=custom-from-server-A, and then in /etc/asterisk/extensions_custom.conf we add that context, which simply contains this:

[custom-from-server-A]
exten => _X!,1,Set(CDR(did)=${SIP_HEADER(X-DID)})
exten => _X!,n,Goto(from-internal,${EXTEN},1)

On Server A, you’d use custom-from-server-B in place of custom-from-server-A.

You can transmit the contents of any Asterisk variable in this manner, but of course you’d probably want to change the custom SIP header name to something that more closely matches the original variable name.  I wouldn’t recommend going hog wild with adding custom SIP headers, but they are a valid technique for passing a few variables or other bits of data between your servers.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.