Need help with multiple locations e911

I was able to work with this when we were chan_sip but since moving to pjsip I am not sure the best way to accomplish this. I have DIDs that have e911 service for 2 locations and was able to use outbound routes to map the extension to dial 911 with the corresponding DID. Now that pjsip allows multiple extension registrations the only constant variable I can use is the static IP we have from our ISP. I saw this in the forum and am having trouble trying to adapt it for our usage to comply with e911. We have a combination of chan_sip and pjsip extensions but have a static IP for each location. How could I get the below to work so that eg. Static IP of would use DID 1234567890 and Static IP of would use DID 1234567891 when dialing 911.

exten => s,1,NoOp()
exten => s,n,GotoIf($[$["${CALLERID(dnid)}" = "911"] | $["${EMERGENCYROUTE}" = "YES"]]?s_CHANNLE_TYPE,1:s_exit,1)

exten => s_CHANNLE_TYPE,1,NoOp()
exten => s_CHANNLE_TYPE,n,GotoIF($["${CHANNEL(channeltype)}" = "PJSIP"]?s_PJSIP_IP,1)
exten => s_CHANNLE_TYPE,n,GotoIF($["${CHANNEL(channeltype)}" = "SIP"]?s_SIP_IP,1)
exten => s_CHANNLE_TYPE,n,Log(NOTICE, <Emergency CID OVERRIDE> Unable to get channel type. CID-IP Mapping not used.)
exten => s_CHANNLE_TYPE,n,Goto(s_exit,1)

exten => s_PJSIP_IP,1,NoOp()
exten => s_PJSIP_IP,n,Set(endpoint_addr=${CHANNEL(pjsip,remote_addr)})
exten => s_PJSIP_IP,n,Set(ip_addr=${CUT(endpoint_addr,:,1)})
exten => s_PJSIP_IP,n,GotoIF($ ["${ip_addr}" != ""]?s_CID_IP_MAP,1)
exten => s_PJSIP_IP,n,Log(NOTICE, <Emergency CID OVERRIDE> Unable to get endpoint ip from PJSIP channel. CID-IP Mapping not used.)
exten => s_PJSIP_IP,n,Goto(s_exit,1)

exten => s_SIP_IP,1,NoOp()
exten => s_SIP_IP,n,Set(ip_addr=${CHANNEL(sip,peerip)})
exten => s_SIP_IP,n,GotoIF($ ["${ip_addr}" != ""]?s_CID_IP_MAP,1)
exten => s_SIP_IP,n,Log(NOTICE, <Emergency CID OVERRIDE> Unable to get endpoint ip from SIP channel. CID-IP Mapping not used.)
exten => s_SIP_IP,n,Goto(s_exit,1)

exten => s_CID_IP_MAP,1,NoOp()
exten => s_CID_IP_MAP,n,GoSubIF(${REGEX("(192\.168\.7\.[0-9])" ${ip_addr})}?s_SetCID,1(5551117777)) ;location1
exten => s_CID_IP_MAP,n,GoSubIF(${REGEX("(192\.168\.8\.[0-9])" ${ip_addr})}?s_SetCID,1(5551118888)) ;location2
exten => s_CID_IP_MAP,n,GoSubIF(${REGEX("(192\.168\.9\.[0-9])" ${ip_addr})}?s_SetCID,1(5551119999)) ;location3
exten => s_CID_IP_MAP,n,GoSubIF(${REGEX("(192\.168\.0\.[0-9])" ${ip_addr})}?s_SetCID,1(5551110000)) ;location4
exten => s_CID_IP_MAP,n,Log(NOTICE, <Emergency CID OVERRIDE> Unable to find CID mapping for ${ip_addr} . CID-IP Mapping not used.)
exten => s_CID_IP_MAP,n,Goto(s_exit,1)

exten => s_SetCID,1,NoOp()
exten => s_SetCID,n,Set(CALLERID(num)=${ARG1})   
exten => s_SetCID,n,Goto(s_exit,1)

exten => s_exit,1,NoOP()
exten => s_exit,n,MacroExit()

Why do you have the same extension in multiple locations? Perfectly normal for people that roam office, but typically not normally a large amount of people.

Some managers (4 of them) have an office at 2 different locations with the same extension.

Phones are on different subnets at each location ?

Does remote_addr change to match each phone’s IP ?

I’m working on something similar, but haven’t finished yet. It’s rough but does pretty much what yours does, feel free to incorporate some/all/none of this:

exten => s,1,Noop(Entering user defined context macro-dialout-trunk-predial-hook in extensions_custom.conf)

; notification for all emergency calls
exten => s,n,GoSubIf($["${EMERGENCYROUTE}"="YES"]?dynamic-emerg-cid,s,1)
exten => s,n(finished),MacroExit

exten => s,1,NoOp(Entering user defined context dynamic-emerg-cid in extensions_custom.conf)
exten => s,n,GotoIF($["${CHANNEL(channeltype)}" = "PJSIP"]?pjsip)
exten => s,n,GotoIF($["${CHANNEL(channeltype)}" = "SIP"]?sip)
exten => s,n,Noop(Unable to get channel type, exiting)
exten => s,n,Goto(exit)

; get ip for pjsip contact
exten => s,n(pjsip),Set(endpoint_addr=${CHANNEL(pjsip,remote_addr)})
exten => s,n,Set(ip_addr=${CUT(endpoint_addr,:,1)})
exten => s,n,Goto(cid)

; get ip for sip peer
exten => s,n(sip),Set(ip_addr=${CHANNEL(peerip)})
exten => s,n,Goto(cid)

; set outbound CID based on regex's
exten => s,n(cid),ExecIf(${REGEX("(192\.168\.7\.[0-9]{1,3})" ${ip_addr})}?Set(CALLERID(number)=5551117777))
exten => s,n,ExecIf(${REGEX("(10\.224\.50\.[0-9]{1,3})" ${ip_addr})}?Set(CALLERID(number)=5551118888))

exten => s,n(exit),return()

I don’t fully understand Regex. Hence my question.

Why not use something like?:

exten => s,n(cid),ExecIf($["${ip_addr:8:2}" = "7."]?Set(CALLERID(number)=5551117777)) 
exten => s,n,ExecIf($["${ip_addr:8:2}" = "50"]?Set(CALLERID(number)=5551118888))

This looks familiar :smiley:
What your ISP provides should be irrelevent since you are managing freepbx and the endpoints yourself. This code looks to matche the IP subnet used for your endpoints. In this example, each location has a seperate /24 subnet. the regex does an exact match of the first 3 octets, then does an any number match for the 4th.
I wouldn’t recommend doing an exact match, but if you wanted to, then just follow the pattern… REGEX("(192\.168\.0\.12)"

Classful networking has not been a thing for decades.

The OP is looking at specific static IP addresses.

@lgaetz’s suggestion is looking at the first three octets being fixed, thus a /24 network. But you could rework the regex however you need.

hahaha…you are right. Meant and prob should have said /24. Thats been fixed now! :slight_smile:

If you network environment is more predictable, then you might wish to isolate a specific octet of the IP, in which case you can use something like this:

exten => s,n,Set(octet_2=${CUT(ip_addr,\.,2)})    ; isolate 2nd octet

With this you can match on the value of octet_2 and not fuss with regex’s at all.


Exactly what I will be doing at a few places I have deployed systems. Originally it was a CID pattern match in the outbound route. But moves have made that a mess. So the subnet of locla networks is the next best solution. Third octet typically for the small business deployments and the second octet for the larger ones.

1 Like

Thinking further, instead of isolating octet 2, I would use a function to strip off the second and third octets and do an exact match that way. It’s probably best not to assume that you will never have an extension on a public IP, in which case a single octet might give a false match.

I prefer the regex method. We had to migrating endpoints at the same physical location to a different subnet, and couldn’t do a cold cut over…so (${REGEX("(10.(10|100).1.[0-9]{1,3})" ${ip_addr})} came in pretty handy

1 Like

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.