I’ve had a lot of issues lately with the CNAM (Caller ID Name) going out from my phone system. People were complaining that they didn’t answer phone calls because they thought it was spam, leading medical staff to have to call patients multiple times.
I reached out to my SIP service provider (ITSP) and asked them if they could adjust my Caller ID Name that is being outpulsed. The response I received surprised me: I was told that what I send out in the P-Asserted-Identity and Contact fields is what is sent out by them. While carrier CNAM dip behavior varies across terminating providers, in order to follow the instructions they gave me, I needed to modify the display name associated with those two headers on outbound SIP INVITE messages. Cue SIP Profiles.
SIP profiles in Cisco IOS XE are used to add, remove, or modify headers in a SIP message. These commands are extremely flexible and can be applied globally across all SIP messaging or as granularly as a specific dial peer.
Today I’m going to walk through building a SIP profile to normalize the Contact and P-Asserted-Identity headers on outbound SIP INVITE messages sent to an ITSP.
First, let’s start with a sample SIP INVITE message going out to the ITSP:
INVITE sip:+15558675309@itsp.example.net:5060 SIP/2.0
Via: SIP/2.0/UDP 198.51.100.2:5060;branch=z9hG4bK12A4
From: "test 1598" <sip:6185550199@198.51.100.2>;tag=1A93BC-2410
To: <sip:+15558675309@itsp.example.net>
Contact: <sip:6185550199@198.51.100.2:5060>
P-Asserted-Identity: "test 1598" <sip:6185550199@198.51.100.2>
Looking at that SIP INVITE message, you can see the two headers Contact: (which has no display name) and P-Asserted-Identity: (which currently has "test 1598"). Our goal is to outpulse "MY COMPANY" (staying within the standard 15-character CNAM limit) on both headers.
Important Information
Before we configure, let’s lay a few ground rules for our SIP profile:
- This will be a request-based SIP profile, not a response profile. Because we are modifying an initial outbound
INVITEmessage, we matchrequest INVITE. - The syntax for a SIP profile does not require quotation marks if there are no spaces, however if there is ANY whitespace in your match or replacement string, IOS requires quotation marks around the pattern. Because of this, always wrap both match and replacement strings in quotation marks.
Let’s write our first SIP profile rule (Contact header)
We will start with the Contact field since we aren’t replacing an existing display name and are only prepending our company name to the existing URI:
request INVITE sip-header Contact modify "" ""
So what did we just do there? We stated that this is a request, specified that it applies to the INVITE message, and targeted the sip-header named Contact with the modify action (if the header didn’t exist we could use add, or remove to strip it). The two sets of quotation marks represent the original match string (regex) and the replacement string.
Let’s start with the original Contact value:
<sip:618XXXXXXX@YYY.YYY.YYY.2:5060>
Since we don’t want to replace the URI itself—only prepend our display name before it—we can capture the angle-bracketed URI using regex:
(<.*>)
By placing parentheses around <.*>, we create Capture Group 1 (\1), which we can reference in our replacement string:
request INVITE sip-header Contact modify "(<.*>)" ""
Now we need to build our replacement string. We want to insert "MY COMPANY" in literal quotes followed by a space and Capture Group 1 (\1). Because the replacement string itself is already enclosed in double quotes in IOS CLI, we escape the literal quotation marks with backslashes (\"):
\"MY COMPANY\" \1
Putting this together into our complete Contact rule:
request INVITE sip-header Contact modify "(<.*>)" "\"MY COMPANY\" \1"
Now we can add this to voice class sip-profiles 1 and apply it to our outbound ITSP dial peer:
Router#config t
Router(config)#voice class sip-profiles 1
Router(config-class)#request INVITE sip-header Contact modify "(<.*>)" "\"MY COMPANY\" \1"
Router(config-class)#exit
Router(config)#
Router(config)#dial-peer voice 102 voip
Router(config-dial-peer)#voice-class sip profiles 1
Let’s write our second SIP profile rule (P-Asserted-Identity header)
Next, let’s modify the P-Asserted-Identity header. First, look at what is in the field starting out:
P-Asserted-Identity: "test 1598" <sip:618XXXXXXX@YYY.YYY.YYY.2>
This time there is already a display name in quotation marks ("test 1598"), which we want to replace with "MY COMPANY" while preserving the <sip:...> URI.
Let’s identify what is currently in the header via regex, escaping the literal quotation marks and grouping the <.*> URI as Capture Group 1:
\".*\" (<.*>)
And our replacement string is identical to the first rule:
\"MY COMPANY\" \1
Putting the full P-Asserted-Identity rule into voice class sip-profiles 1:
Router#config t
Router(config)#voice class sip-profiles 1
Router(config-class)#request INVITE sip-header P-Asserted-Identity modify "\".*\" (<.*>)" "\"MY COMPANY\" \1"
Now that we have built these… how can we test?
On a live router, you can verify outbound SIP headers using:
Router#terminal monitor
Router#debug ccsip messages
(Be sure to run undebug all once you have captured your test call.)
Even better, before applying a SIP profile to a production CUBE, you can test your exact voice class sip-profiles syntax against a sample SIP message using Cisco’s online SIP Profile Test Tool:
For more information about SIP profiles, check out Cisco’s configuration guide:

Jaron Davis
Unified Communications Architect specializing in enterprise Zoom, Microsoft Teams, Cisco UC modernization, SIP/VoIP infrastructure, and systems architecture.