Freenum/ISN Logo

The Freenum/ISN Cookbook 2007-10-25

This cookbook provides a short introduction to the Freenum dialing system, which uses a dialing and directory method called ISN (ITAD Subscriber Numbers). This document includes instructions for enabling Freenum/ISN calling for your campus, enterprise, or service provider domain. Freenum/ISN is a simple way to provide your SIP users with numeric addresses that can be dialed from devices that offer poor or no support for entry of alphanumeric SIP URIs. Recipes for several popular SIP platforms, including Asterisk, Cisco, SER, and FreePBX are provided.


About Freenum/ISN

ISNs (ITAD Subscriber Numbers) provide a method for inter-domain numeric SIP addressing. An ISN is formed by joining a domain-local subscriber number to an ITAD (Internet Telephony Administrative Domain) number, using an asterisk as the delimiter. For example, subscriber 1234 in ITAD 256 would have ISN: 1234*256

ISNs were inspired by the INOC-DBA hotlink numbering scheme, which uses autonomous system numbers (ASNs) as telephony domains. This method worked well in a small community of large network operators, but a more general solution was needed which was available to a larger community. The Freenum/ISN method relies upon the DNS and does not rely upon ASNs as the base identifier. There existed already an IANA-approved number which was intended for use by organizations who wished to provide telephony routing for their users. This is the ITAD number, and it is described in RFC3219.

The Freenum project uses the ISN method of dialing and provides a base DNS zone in which ITAD registrants may publish their NAPTR records directly or may have their ITAD DNS records delegated to them. The "freenum.org" zone provides this DNS infrastructure, and there exist on this site automated tools which allow ITAD registrants to automatically update their DNS and participate in the larger directory services functions of the Freenum project.

Freenum/ISN dialing is not a replacement for alphanumeric SIP URIs. It is, rather, a numeric-only overlay onto existing SIP URI endpoint directory structures that is more accessible to the vast majority of users who are using telephone-like devices with no easy alphanumeric entry method. Freenum/ISN is also unburdened by the complexities of the E.164 (PSTN) numbering system, which is what the world's telephony networks rely upon today for routing decisions. There are no costs, no geographic boundaries, and no prerequisites for inclusion in the Freenum/ISN dialing system other than a set of SIP endpoints connected to the public Internet.

The goal of the Freenum/ISN project is to allow end-users to more easily and efficiently reach each other on various media networks, such as a SIP voice platform. There are several ways in which the keypad-friendly Freenum/ISN dialing system provides that ease and efficiency, ranging from practical realities of phone handset design to avoidance of political issues in PSTN-based phone numbering resource hierarchies. This document will not describe them all; please see the freenum.org site for more details and white papers as they are published.


2. Requesting an ITAD for your Domain

ITADs are currently allocated free of charge to any organization who wishes to register one. IANA maintains the registry for ITADs. To request an ITAD from IANA, point a web browser to http://www.iana.org/cgi-bin/assignments.pl and complete the form. The form is replicated here, along with suggestions for completing each field:

Table 1. IANA Website

iana.png
  1. Person responsible for this application.
  2. The email address of the person who is responsible for this application. Use of role accounts (e.g. support@bigu.edu) in this field, appears to be acceptable.
  3. Put something like this here: "I would like to register an ITAD (Internet Telephony Administrative Domain) number with IANA for my organization."
  4. Put something like this here: "I am requesting this registration be made in the general IANA directory of ITAD number listings, found at http://www.iana.org/assignments/trip-parameters."
  5. "I am requesting an ITAD assignment so that my organization may participate in the ISN trial (http://www.freenum.org/) and any ITAD peering fabrics that may follow."
  6. "ITADs (IP Telephony Administrative Domains) are defined in "Telephony Routing over IP (TRIP)" [RFC3219]." Also include your POSTAL MAILING ADDRESS as this is a requirement for ITAD registrations.

After you receive confirmation of your ITAD registration from IANA, you will shortly thereafter receive an automated email message to the address which you listed in Item 2 in the application form. This message will be from the Freenum/ISN project, and it will contain the password to your FASST (Freenum Automated Self-Service Tool) account on the freenum.org website, which allows for on-line administration of your DNS entries and organizational details.

If you do NOT recieve an email message from admin@freenum.org within two business days of your ITAD being visible in the http://www.iana.org/cgi-bin/assignments.pl page, please send email to admin@freenum.org and the discrepancy will be investigated. Please include your ITAD number. (Hint: often, people have spam filters on the addresses they list in the IANA registration form, and our automated systems cannot reach the recipient. Please check your spam filters before contacting the administrators of Freenum. You can re-send your password data from the signin page on the Freenum Automated Self-Service Tool to test your filter's accuracy.)


3. Publishing your Freenum/ISN information in the DNS

Once IANA allocates an ITAD for your domain, you must place pointers to it in the Domain Name System (DNS) so that the rest of the world can route ISN calls to you properly. Every ISN has a corresponding representation as a domain name. SIP proxy or user agent routing an ISN call transforms <subscriber>*<itad> into <subscriber-in-inverted-ENUM- format>.<itad>.freenum.org, and then performs a series of DNS resolutions (NAPTR, SRV, and A) before generating a SIP INVITE to the destination ITAD.

For example, to call extension 1234 at ITAD 256 the initiating SIP proxy or user agent would perform a NAPTR resolution on 4.3.2.1.256.freenum.org. The NAPTR response will result in a SIP URI such as sip:1234@loligo.com or sip:janedoe@bigu.edu that can be used to route the call in the usual manner (e.g. through additional SRV and A records resolutions).


3.1. Creating DNS Entries for Your ITAD

There are two options for creating DNS entries for your ITAD. Either method requires use of the Freenum/ISN FASST (Freenum Automated Self-Service Tool) which is a web-based console for updating information about your ITAD number in the freenum.org DNS zone. Any changes to the FASST system require up to 40 minutes to be re-distributed to all of the nameservers which are authoritative for freenum.org.

  1. If you have only a single SIP server and you don't want to deal with the hassle of creating a zone file, you may request that a NAPTR record be inserted directly in the freenum.org zone for your ITAD. This is what the majority of Freenum/ISN participants do, as there are typically only SIP methods being used, and typically also only one SIP proxy/PBX/gateway being used in the organization.

    You may point your entire ITAD zone at a SIP proxy or gateway without delegation of the zone to your name servers. What is needed is a single wildcard record like this to be entered directly in the Freenum/ISN (freenum.org) base zone file:

    *.xxx.freenum.org IN NAPTR 100 10 "u" "E2U+sip" \
        "!^\\+*([^\\*]*)!sip:\\1@sip.big.edu!" .
    
    (line is wrapped for ease of reading)
    

    This means "take any number given, ignore a leading '+' sign (if given), and then take everything to the left of the '*' sign (if given) as the number, or just use the whole number provided if there is no '*' sign, and create a SIP URI out of it." This would take any of these strings: 12345*111, +12345*111, +12345, 12345 and turn it into 12345@sip.big.edu. There are example NAPTR records in the FASST web interface that require merely that the hostname is changed before submission if you choose to have the records hosted directly by the Freenum/ISN project nameservers. No DNS modification is required at all on your servers if this method is used, as all data and queries will be resolved by the freenum.org masters.

  2. If you have your own name servers and ENUM-like DNS data, you may choose to have your ITAD zone in the freenum.org domain delegated to your nameservers for local control. This is an advanced method, and is suggested only for those who are very familiar with DNS administration, and NAPTR/ENUM administration in particular.

    The Freenum.org FASST administration tool allows you to delegate your ITAD zone to your nameservers. As an example, if your ITAD was 123, then you could delegate 123.freenum.org to your own set of authoritative resolvers and manage your own subscriber portions of the ISNs internally to your organization.

    After you delegate the zone on the FASST interface, create a new zone in your nameservers called xxx.freenum.org, where xxx is your ITAD number. At this point you have a choice: you may insert one or more NAPTR records (as above in the wildcard example) and designate all subsequent ISN routing to a SIP proxy; or you may populate your ISN zone file with the subscriber numbers for your entity in ENUM-like format. This may be as simple as creating a symlink of xxx.freenum.org to your existing ENUM extension zone. Note that in this fashion you can create one-to-one mappings of subscriber numbers to SIP URI's like john.whorfin@big.edu, thus hopefully meshing well with any existing SIP or ENUM infrastructure that exists already at your institution. Remember that the ISN method does not require numeric SIP addresses as an ultimate destination - it can provide mapping between a numeric identifier and a non-numeric existing catalog of SIP identities in a way that lends itself to easy scripted creation of zone file mappings. (1234*123 = sip:john.whorfin@big.edu)


3.2. Testing Your DNS Configuration

To test to see if your ISN mappings are correct so that others may find you, try looking at a valid subscriber number for your ITAD zone name. Assuming you have a valid ENUM entry for 4.3.2.1 in your zonefile (or have a wildcard) and your ITAD is 254, then this should work after DNS updates have been put in place.

dig @my.nameserver.edu NAPTR 4.3.2.1.254.freenum.org.

This should respond with the NAPTR record you have in place. If you get an "NXDOMAIN" then something else is wrong with DNS resolution, and you should debug as you would a normal DNS issue.

You may also wish to perform these tests against the freenum.org authoritative resolvers to ensure that there are no issues with stale DNS records on your local resolvers. Use "anyns.pch.net" as a resolver, as this nameserver is one of the primary authoritative resolvers for freenum.org and has dozens of mirrors around the globe answering on that address.

dig @anyns.pch.net NAPTR 4.3.2.1.254.freenum.org.

There is also TXT data stored for each organization in a somewhat-X.500 compliant list in the info.freenum.org zone. This is more of a convenience for the administration of the nameserver records, but also may be of some use to participants.

dig @my.nameserver.edu TXT 254.info.freenum.org.

A web-based version of dig may be found here: http://www.fpsn.net/index.cgi?pg=tools&tool=web-dig


4. Configuring Your Domain for Inbound ISN Calling

This is a very site-specific task, and so details about how to map numeric subscriber numbers to the user community on the local SIP proxy are left to the local administrator. In it's most basic method, your SIP system needs to accept a number as a username, so (for example) 1234@yourproxy.yourdomain.com would end up ringing the "owner" of extension 1234.

If the local dialplan just maps numbers directly through to extensions on an Asterisk or Cisco gateway to a PRI to your main PBX, then this will be relatively easy. If the dialplan is mapping subscriber numbers to SIP URI's through a database, this is more complex, but it is assumed that the local administrator has the ability to configure their SIP proxy/gateway to receive inbound INVITEs from foreign sources. This can be accomplished through entry of SIP URIs into the DNS (if the zone is delegated to the organization and each extension has an ENUM-like entry) or it can be done on the proxy at the moment a call is received - this is up to the local administrator.


4.1. Sample Configuration: Inbound for SER

This section demonstrates how inbound ISN routing can be made to work on SIP Express Router (SER).

Exactly how inbound ISN calls (those destined for your users) are routed is highly site-specific. In the implementation shown here, a user's primary identity is an alphanumeric SIP URI equivalent to his email address. ISNs are aliases for these primary identities and phone numbers are fall-back routes to use when a user has no registered SIP user agents (classical SIP.edu). Alternatively, a domain might decide that the ISN is the primary identity with which a user agent registers.

In the example used here, all ISNs are stored in SER's MySQL aliases table with username equal to ISN prepended by __isn__ and contact equal to the user's URI. This is to avoid potential conflicts with actual usernames and their SIP.edu (telephone number aliases). The aliases table is updated nightly by an external utility that extracts email address and telephone number for all employees from the corporate person directory. Each user is assigned an ISN equal to the last four, five, or six digits of his telephone number (whichever is shortest and non-ambiguous). For example, the aliases table might contain the following bindings:

username contact
bob sip:2123217031@bigu.edu
__isn__ sip:bob@bigu.edu

In the ser.cfg fragment shown below, inbound ISNs are identified and delegated to the route[4] block. The structure of an inbound ISN will differ depending on the ISN NAPTR record used by the domain. Option 1 assumes that inbound ISNs will be purely numeric, while Option 2 assumes that a full ISN (including the asterisk and the local ITAD) will be received.

route{
      # ...

      # Two options (comment out one).

      # Option 1: Any string of digits in the user part is regarded
      as
      # an ISN.  This is what is expected when using an ISN NAPTR
      like
      # this:
      #   *.255           IN      NAPTR   100     10      "u"
      "E2U+sip"
      #   "!^\\+*([^\\*]*)!sip:\\1@sip.bigu.edu!" .
      if (uri=~"sip:[0-9]+@.*sip.bigu\.edu") {
          route(4);   # Route inbound ISN calls
      };

      # Option 2:
      #   *.255           IN      NAPTR   100     10      "u"
      "E2U+sip"
      #   "!^\\+*([^\\*]*)!sip:\\1\\*255@sip.bigu.edu!" .
      if (uri=~"sip:[0-9]+\*255@.*sip.bigu\.edu") {
          # substr_uri() requires textops module
          subst_uri('/sip:([0-9]+)\*255@(.*)/sip:\1@\2/g');
          route(4);   # Route inbound ISN calls
      };

      # ...
  }

  # Route inbound ISN call
  *route[4]* {
      # Assert that URI is in proper format
      if (! (uri=~"sip:[0-9]+@.*sip.bigu\.edu")) {
          xlog("L_CRIT", "%Tf: route[4] called with improper
          URI\n");
          break;
      };

      prefix("__isn__");
      xlog("L_INFO", "%Tf: Routing inbound ISN Call %ru (From
      [%fu], To [%tu])\n");
      if (!lookup("aliases")) {
          xlog("L_ERR", "%Tf: Invalid ISN %ru (From [%fu], To
          [%tu])\n");
          sl_send_reply("404", "Not Found");
          break;
      };

      # Check whether user is reachable via a registered user agent
      (UA)
      if (!lookup("location")) {
          # If no registered UA, call desk phone (SIP.edu)
          if (!lookup("aliases")) {
              xlog("L_ERR", "%Tf: Rejecting Call %ru (From
              [%fu], To [%tu])\n");
              sl_send_reply("404", "Not Found");
              break;
          };
      }; # End of lookup location block
      # Relay the message
      if (!t_relay()) {
          sl_reply_error();
      };
  }

5. Configuring Your Domain for Outbound ISN Calling

5.1. Some General Comments and Options

It may be necessary to create a local prefix that users enter to distinguish ISN calls. The question of what prefix to use (if any) is purely a local matter. Telephony planners must consider conflicts with legacy local prefixes, the traditions of the campus/enterprise dialing plan, the capabilities of equipment, and other issues. Consider an ISN domain that uses "012" as a local prefix (without loss of generality, the examples and recipes throughout this document all use "012" as a local prefix). When a local user dials 0122425*256, the local proxy or PBX must remove the "012" before passing the remaining ISN 2425*256 to the next step of the dialing process.

A related issue that will be faced in environments with standard DTMF handsets, is how to identify the end of an ISN dialing string. Since ISNs are variable-length, a timer-based end-of-dial decision may be necessary.

Once a number is evaluated into an ISN (by whatever mechanism) by your SIP gateway or proxy, it needs to perform an ISN lookup which leads to a SIP URI. This can be done in one of three ways - pick one:


5.1.1. Option 1: Native ISN Lookup

Your proxy or gateway may have enough intelligence and scriptable capability to tear the dialed sequence apart and perform a "native" ISN lookup. This scripting capability may be built into your platform, or some language such as Perl, Python, C, or even shells scripting may be used depending on your system. The format of <subscriber>*<itad> can be recognized and turned into distinct strings for ENUM-like lookup. Your system should perform a lookup by taking the ITAD portion of the ISN and prefixing it onto freenum.org as the zone name. Then, the subscriber number is inverted and turned into an ENUM-like zone prefix. An example is easier than description: If the user dials 2203*256 the ENUM-like lookup that occurs is 3.0.2.2.256.freenum.org. The NAPTRs (if any) that are returned as a result are parsed in the manner that is according to ENUM rules; hopefully there is a protocol URI in the response of the type you are seeking (typically, SIP). Instructions for both SER and Asterisk are included below as demonstrations of native ISN lookup from within a SIP proxy or PBX system.


5.1.2. Option 2: Using the Freenum SIP Redirector

Option 2: Your gateway or proxy can perform a SIP lookup on the ISN against a publicly accessible Freenum SIP proxy configured for this purpose. As a public service, Freenum operates a SIP proxy (public.freenum.org) that will perform ISN-to-SIP rewrites. If you send your SIP query in the format: ::<subscriber>*<ITAD>@public.freenum.org then any valid ISN lookup by the Freenum proxy will result in a "302 Redirect"-style response. Note that this will only respond with the first (highest preference) URI in any list of NAPTRs, including tel or other URI methods. Your gateway must be able to parse the reply. It is anticipated that for the forseeable future that almost all replies will be SIP URI formatted responses.


5.1.3. Option 3: Resolve Freenum/ISN Through Private ENUM

Your gateway or proxy can perform an ENUM lookup on the ISN against the publicly accessible ISN rewriting DNS resolver, which is also provided by Freenum as a public service. This resolver has been written to specifically re- write ENUM queries with ISN format and convert them to appropriate ISN lookup syntax. This re-write on the Freenum resolver does something like this:

6.5.2.*.3.0.2.2.e164.arpa. -> 3.0.2.2.256.freenum.org

Currently, the freenum.org zone is what is used to convert any e164.arpa. lookups into an ISN-style search. It is also possible to use the freenum.org zone as an ENUM-like root zone name.

In order to use this search method, you MUST have your gateway or proxy exclusively use the Freenum resolver IP address as the only resolver that the device uses. All other query types will be passed through unchanged by the Freenum resolver to a set of "normal" resolvers; only NAPTRs containing * and which are for e164.arpa. suffixed requests will be altered. If the NAPTR does _not_ contain a "*" within the record, then it will be unmodified (i.e.: you can make "normal" ENUM or ENUM-like queries through this resolver without worry, as well as any other queries for record types like A, CNAME, or SRV which will be unmodified and returned as would a normal DNS resolver.

The DNS resolver which is configured to do this is located on the same host as the primary web services for Freenum.org - 216.218.159.179. You may point your /etc/resolv.conf or other resolution configuration sections to this name server in order to have that resolver do ISN re-writes for your ENUM-capable equipment.


5.2. Sample Configuration: Outbound for SER

To route outbound ISN calls (those originating from within the domain served by SER), SER must be configured to recognize a request URI containing a valid ISN and must resolve the ISN before routing the message further. Domains, especially those with complex legacy dialing plans, may chose a local prefix to identify dialed ISNs (012 is recommended).

The ser.cfg fragment below show logic for recognizing dialed ISNs. The first option is to be used when a local ISN prefix is in use, while the second option identifies an ISN purely by the structure of the request URI (an asterisk embedded between two strings of digits). All other routing logic is elided in the example.

route{
      # ...

      # Two options (comment out one).

      # Option 1: Local ISN prefix
      if (uri =~"^sip:012") {
          strip(3);   # Remove 3-digit local ISN prefix
          route(3);   # Route outbound ISN calls
      };

      # Option 2: No local ISN prefix
      if (uri =~"^sip:[0-9]+\*[0-9]+@") {
          route(3);   # Route outbound ISN calls
      };

      # ...
  }

Once it has been recognized that an ISN is being called, it must be resolved through an ENUM-like NAPTR resolution. Unfortunately, SER's ENUM module imposes some restrictions that prevent it from being used for ISN resolution. The route[3] block (shown below) demonstrates two options of working around these limitations.

The first option is to use Freenum's ISN resolver, which will perform the resolution and issue a 302 Redirect-style response. Note that this will only respond with the first (highest preference) URI in any list of NAPTRs, including tel or other URI methods. Also note that this method relies on an external service with no caching of results to fall back on should use of that service be disrupted.

The second option is to perform the resolution locally, using SER's exec_dset method and an external ISN resolver (isn-resolv.pl) that is run locally. Open source code for isn-resolv.pl may be found in Appendix A.

# Route outgoing ISN calls
  route[3] {
      # Assert that uri is in proper format
      if (! (uri =~"^sip:[0-9]+\*[0-9]+@")) {
          xlog("L_CRIT", "%Tf: route[3] called with improper
          ISN\n");
          break;
      };

      # Two options (comment out one).

      # Option 1: Freenum's ISN resolver
      rewritehostport("public.freenum.org:5060");
      if (!t_relay()) {
          sl_reply_error();
      };

      # Option 2: Local Perl NAPTR resolver (see code below)
      if (!exec_dset("/usr/local/bin/isn-resolv.pl")) {
        sl_send_reply("404", "Not Found");
        break;
      } else {
          xlog("L_INFO", "%Tf: Routing outbound ISN Call %ru
          (From [%fu], To [%tu])\n");
          # Relay the message
          if (!t_relay()) {
              sl_reply_error();
          };
      };
  } # end of ISN route block

5.3. Sample Configuration: Asterisk (Inbound and Outbound)

The sample configuration below demonstrates ISN integration with Asterisk and a PBX and handles both inbound and outbound ISN calling. Note that the configuration assumes Asterisk version 1.2 or newer. For older versions, see the commented patch at the end.

To use this configuration, just cut/paste the whole blob into your config file and use "include => isn" somewhere in your main dialing context.

Once installed, these scripts will allow your users to use the prefix "012" to identify dialed numbers as ISNs. So, for example, dialing 0121234*256 will ring the ISN 1234*256. For other test numbers, see Section 5.5. Testing Outbound Calling.

; -- Start Asterisk extensions.conf Config >=1.2 --
;
; 2005-11-06 jtodd@loligo.com
;
; This is a reasonably complete, but minimalist, configuration
;  for an Asterisk server connected to a PBX, which provides
;  inbound SIP URI-to-extension mapping (which by default is
;  also ISN inbound mapping) and then also performs outbound
;  ISN dialing (PBX-to-SIP) conversion.
;
; This will be a quick instruction on how to make an Asterisk
;  server function as a very basic inbound session border
;  controller (SBC) which then will sit in front of an existing
;  PBX with a PRI attaching Asterisk to the PBX.
;
; Anyone elsewhere on the Internet dialing the ISN of
;  "1415551234*255" will be routed to extension "51234" on the
;  PRI, which then hopefully will ring the phone on the desk
;  of that person.  Similarly, dialing "51234*255" will go to
;  the same place.
;
; The second part of this dialplan is to take calls from
;  the PBX
;
;  Further assumptions will be:
;
;   - the PBX uses 5 digit extensions
;
;   - the PBX passes 5 digit extensions in as caller ID
;     for calls from the PRI
;
;   - the PBX routes all calls from all phones starting with
;     "012" in the dialed string to the PRI on this Asterisk
;     server.
;
;   - the PBX has PSTN connectivity that handles calls for
;     the E.164 ranges of 1-415-555-1xxx and 1-451-999-8xxx
;
;   - there are no "black" or "white" lists that are desired
;
;   - this demonstration server is called sip.bigu.edu, and
;     has matching forward/inverse records to that extent
;
;   - SRV records are in place for this domain, such that
;     requests to "51234@bigu.edu" get mapped to this server.
;     This means that the following line is in the zone file
;     in the "bigu.edu" level:
;
;      _sip._udp.bigu.edu. SRV 0 0 5060 sip.bigu.edu.
;
;   - the ISN for this demonstration is "255"
;
;   - the DNS for this ISN is (long line, careful of wraps):
;
;      *.255.freenum.org IN NAPTR 100 10 "u" "E2U+sip"
;      "!^\\+*([^\\*]*)!sip:\\1@sip.bigu.edu!" .
;
;      (yes, it's to "sip.bigu.edu" since it's pointless to force
;       an SRV lookup if this is a "behind-the-scenes" method.)
;
;   - The PRI is configured to communicate with the PBX, and the PBX
;      is expecting 5 digit extension numbers as dialstrings.
;
;   - The PRI is on Zap/g1 ("group" 1).  Here are some demonstration
;      files, but you will probably need to read the docs to get
;      the correct configs:
;      /etc/zaptel.conf:
;       loadzone = us
;       defaultzone = us
;       span=1,1,0,esf,b8zs
;       bchan=1-23
;       dchan=24
;      /etc/asterisk/zapata.conf:
;        group=1
;        context=isn
;        signalling=pri_cpe
;        switchtype=national
;        pridialplan=unknown
;        usecallerid=yes
;        channel => 1-23
;
;   - The sip.conf file has the following lines in it in the [general]
;      stanza:
;      ; Send calls from "the Internet" to the [from-internet] context
;      context=from-internet
;      ; Allow only "free" codecs.  You may change this to
;      ;  just ulaw and alaw if this is a CPU-constrained box.
;      disallow=all
;      allow=ulaw
;      allow=alaw
;      allow=gsm
;      allow=ilbc
;      allow=speex
;      ; Hang up any calls that don't have media flowing
;      rtptimeout=60
;
; If you want to use LDAP, this example does not cover that
;  example, as it is "advanced magic."  If you wish to give it
;  a try, see http://www.mezzo.net/asterisk/app_ldap.html for
;  an LDAPget lookup method that can be added to Asterisk.
;
;
;
[from-internet]
;
; Catch all inbound numbers that seem to be for us, and send
;  them to context [from-internet2] with only the last six
;  digits of the dialed number.
;
; Note that for ISN dialing, the number of digits presented is
;  a function of the regular expression that is in the DNS for
;  your ISN zone.  Typically, the whole number will be passed
;  through to the receiving server instead of the regexp trying
;  to be clever.  Asterisk will do all the conversion work, no
;  matter what format the number is passed in as.
;
exten => _14155551XXX,1,Goto(from-internet2,${EXTEN:6},1)
exten => _4155551XXX,1,Goto(from-internet2,${EXTEN:5},1)
exten => _51XXX,1,Goto(from-internet2,${EXTEN},1)
;
exten => _14159998XXX,1,Goto(from-internet2,${EXTEN:6},1)
exten => _4159998XXX,1,Goto(from-internet2,${EXTEN:5},1)
exten => _98XXX,1,Goto(from-internet2,${EXTEN},1)
;
;
; Include email-address style name context from [usernames]
;
include => usernames
;
; Include some quick test destinations that can be used for
;  debugging by other people.  These are not standardized names
;  yet, but it seems that they're a good idea for a network of
;  experimental or test-heavy destionations.
;
include => tests
;
; If no matches are in any of the above rules, then the call
;  should be send to the "i"nvalid rule.  This will send a
;  SIP error back to the caller.
;
exten => i,1,Congestion
;
; If someone hangs up before this context quits, we need an
;  "h"angup extension.
;
exten => h,1,Hangup
;
; Advanced Dialplan-Fu: if you have another internal SIP
;  proxy, you could "include" a context in [from-internet]
;  which points usernames at alternate SIP URIs and actually
;  creates a SIP INVITE to them, like this:
;
;  [more-usernames]
;  exten => reno,1,Dial(SIP/reno@pbx.cs.bigu.edu)
;  exten => ptommy,1,Dial(SIP/perfect@asterisk.ee.bigu.edu)
;
;
;
[from-internet2]
;
; Here is where we pass off the call onto the PRI.  The
;  call is capped at 3 hours (to prevent "zombies") and then
;  it is simply handed to the PRI, since we already normalized
;  the extensions to the "expected" 5 numeric digits which
;  the PBX is looking for.
; If you are running a very recent version of Asterisk, you
;  may need to comment out the AbsoluteTimeout line and uncomment
;  the Set line below it, as AbsoluteTimeout is being phased out.
;
exten => _XXXXX,1,AbsoluteTimeout(10800)
; exten => _XXXXX,1,Set(TIMEOUT(absolute)=10800)
;
; Now dial!  There are no parameters, since this system is
;  not acting as a voicemail system or doing any clever stuff
;  to the calls; this is purely a passthrough.
;
exten => _XXXXX,2,Dial(Zap/g1/${EXTEN})
;
; If we get to priority 3, something is wrong.  Send congestion,
; hangup.
;
exten => _XXXXX,3,Congestion
;
; Handle "T"imeouts, and "h"angups.
;
exten => T,1,Hangup
exten => h,1,Hangup
;
; This is the end of the "core" of the inbound-from-Internet
; dialplan.
; Pretty simple, eh?
;
;
;
[usernames]
;
; This context is a simple list of all the alphanumeric destinations
;  that are associated with extensions.  This is the "ugly" way to
;  do it.  You could also use the "#include <filename>" directive,
;  which would pull in this context (including context name) from
;  an external file, which you could create periodically.  Or LDAP
;  could be used.  Or a "System" call which would run a Perl script
;  that would get run at the top of your [from-internet] context that
;  would query a database and do a mapping.  There are many methods;
;  this is just the simplest one to show.
;
; Each username is mapped to the five digit extension of their
;  telephony device, since we're going to be sending the calls to
;  their phones.  If they also register to a SIP proxy or this
;  Asterisk server as their username, then you're outside the scope of
;  this simple example.  :-)
;
exten => john.whorfin,1,Goto(from-internet2,51322,1)
exten => penny.preddy,1,Goto(from-internet2,51936,1)
exten => john.smallberries,1,Goto(from-internet2,98339,1)
; etc. etc. etc.
;
;
[tests]
;
;  Destinations used for testing purposes.
;
; "echo": Set timer on this call to 500 seconds, play announcement,
;  echo
;
exten => 999,1,Goto(echo,1)
exten => echo,1,AbsoluteTimeout(500)
; Newer versions of Asterisk may need the newer "Set" method
;exten => echo,1,Set(TIMEOUT(absolute)=500)
exten => echo,2,Playback(demo-echotest)
exten => echo,3,Echo
;
; "date": Play date/time, hangup
;
exten => 998,1,Goto(date,1)
exten => date,1,Answer
exten => date,2,Wait(2)
exten => date,3,SayUnixTime
exten => date,4,Hangup
;
;
;
; ======================================
;
; This is for OUTBOUND ISN lookups/calls.
;
; The PBX will send calls with the digits "012" to the Asterisk
;  server, and leave everything else unmodified.
;
; The prefix for ISN numbers on this local system is "012" so
;  strip off those digits when presenting.  Your site may be
;  different.  The system will handle ISN dialing with or without
;  the leading three digit prefix.
;
; This method uses the "new" ENUMLOOKUP functions to look up ISN
;  numbers in the DNS.  The parsing for ISN numbers was
;  specifically included in the code, so no fancy re-writing of
;  the number is required by the dialplan administrator - Asterisk
;  takes care of the internal swapping and zone creation that turns
;  "1234*256" into "4.3.2.1.256" and then adds the zone.
;
; If you have an Asterisk server already, you can just clip this
;  context out and include it into your main dialing context via
;  the "include => isn" directive, or the three lines in the [isn]
;  context can just be cut/pasted into one's main dialplan context;
;  it's up to the administrator.
;
; This method uses the first SIP result from the list of valid
;  NAPTRs for an ISN lookup.  If you want to iterate through the
;  NAPTRs, then you will need to learn more about the ENUMLOOKUP
;  function and it's abilities - see "README.enum" in the docs
;  directory in the Asterisk source code tree.
;
; There is little error handling in this very brief example.  If the
;  number fails lookoup in the ISN root, then a recording should
;  probably be played.  Same with if the SIP call fails.  We just
;  use "Congestion" to indicate an error, since this is a trivial
;  example.
;
; The zone used is currently "freenum.org" as of 2005-11-06.  This
;  zone is subject to change; please see the http://www.freenum.org/
;  site for details, if available.
;
; Note the "i" in the ENUMLOOKUP function call; this may or may not
;  be required, but it doesn't hurt to leave it there if you are
;  running an older copy of the function which doesn't need the "i"sn
;  specifier.
;
; SPECIAL NOTE: Admittedly, these have not been tested with anyone's
;  "real" PBX.  Therefore, if your PBX sends overlap dial in certain
;  ways, it may not work correctly on the matching sequence.  If this
;  is the case, PLEASE contact John Todd (jtodd@loligo.com) and he
;  will attempt to come up with a site-specific workaround and then
;  include the notes in this example.
;
[isn]
;
; Match on the prefix of "012" followed by one or more digits,
;  followed by a "*", followed by one or more digits.  Also match on a
;  straight ISN (one or more digits starting with 1-9 as the first
;  digit, followed by "*", followed by one or more digits.)
;
; If a match is found, jump to the [isn2] context to create the SIP
;  call.  The PRI channel will then be connected to the SIP channel.
;
exten => _012.,1,Goto(isn2,${EXTEN:3},1)
;
;
; Hang up on invalid or hangup error conditions.
exten => i,1,Congestion
exten => h,1,hangup
;
;
;
[isn2]
;
; First, configure an outbound caller ID which at least looks
;  like a SIP URI for the outbound call.
;
; We're going to assume that the 5 digit extension of the PRI
;  call is valid, so re-set it with the trailing "@bigu.edu" for
;  a complete SIP URI.  If the name field is null, then set the
;  caller ID name to "Big University", otherwise leave alone.
;
exten => _X.,1,Set(${CALLERID(num)=${CALLERID(num)}@bigu.edu)
exten => _X.,2,GotoIf($["${CALLERID(name)}"=""]?3:4)
exten => _X.,3,Set(${CALLERID(name)="Big University"})
;
; Now, set a maximum timer on the call to prevent zombies (3 hours)
;
exten => _X.,4,AbsoluteTimeout(10800)
; Newer versions of Asterisk may complain about AbsoluteTimeout
; exten => _X.,4,Set(TIMEOUT(absolute)=10800)
;
; Do the ENUMLOOKUP on the number in the "freenum.org" zone...
;
exten =>
;_X.,5,Set(isnresult=${ENUMLOOKUP(${EXTEN},sip,i,freenum.org)})
;
; If the result is not null, dial the SIP destination.  If no
;  answer in 100 seconds, go to "Congestion".  This ends the
;  process in either case (success or failure.)
;
exten => _X.,6,GotoIf($["${isnresult}"=""]?8:7)
exten => _X.,7,Dial(SIP/${isnresult},100)
exten => _X.,8,Congestion
;

; Include standard failure mode extensions for "h"angup,
;  "T"imeout, and "i"nvalid results
;
exten => h,1,Hangup
exten => i,1,Hangup
exten => T,1,Hangup
;
;
; -- END extensions.conf EXAMPLE --
;
; NOTE TO USERS OF OLDER VERSIONS OF ASTERISK
;
; If you're running an older version of Asterisk, you may need
;  to remove [isn2] and replace it with this modified version
;  of code, which uses an external public resolver to map ISN
;  dial strings to SIP URIs.  Ensure that you have the sip.conf
;  option of "promiscredir=yes" set. (Comments removed for brevity)
;
;[isn2]
;exten => _X.,1,SetCIDNum(${CALLERID}@bigu.edu)
;exten => _X.,2,GotoIf($["${CALLERID}"=""]?3:4)
;exten => _X.,3,SetCIDName("Big University")
;exten => _X.,4,AbsoluteTimeout(10800)
;exten => _X.,5,Dial(SIP/${EXTEN}@public.freenum.org,100)
;exten => _X.,6,Congestion
;exten => h,1,Hangup
;exten => i,1,Hangup
;exten => T,1,Hangup
;

5.4 Sample Config: Cisco (Outbound to PRI)

Contributed by Jesse M Hindmarsh of LightspeedTech

!
hostname sip-gw
!

!

memory-size iomem 15
network-clock-participate wic 1
ip cef
!
!
!
!
ip domain retry 3
ip domain timeout 5
ip domain name lightspeedtech.net
ip name-server 74.212.22.251
!
!
isdn switch-type primary-dms100
!
!
voice call send-alert
!
voice service voip
 sip
  ds0-num
!
!
voice class codec 1
 codec preference 1 ilbc
 codec preference 2 g729r8 bytes 40
 codec preference 3 g723r63 bytes 96
 codec preference 4 g726r16 bytes 80
 codec preference 5 g729br8
 codec preference 6 g711ulaw
 codec preference 7 g711alaw
!
!
!
voice translation-rule 1
 rule 1 /^18/ /*18/
!
!
voice translation-profile 800-To-FWD
 translate called 1
!
!
voice-card 0
!
!
controller T1 0/1/0
 framing esf
 clock source internal
 linecode b8zs
 cablelength short 133
 pri-group timeslots 1-6,24
!
!
interface FastEthernet0/0
 ip address 74.212.22.237 255.255.255.224
 duplex auto
 speed auto
!

!
interface Serial0/1/0:23
 no ip address
 encapsulation hdlc
 isdn switch-type primary-dms100
 isdn protocol-emulate network
 isdn incoming-voice voice
 isdn map address . plan isdn type national
 isdn send-alerting
 no cdp enable
!
!
interface Vlan1
 no ip address
!
ip default-gateway 74.212.22.254
ip route 0.0.0.0 0.0.0.0 74.212.22.254

!
!
no ip http server
no ip http secure-server
!
disable-eadi
!
!
!
!
!
!
control-plane
!
!
voice-port 0/1/0:23
 output attenuation 2
 echo-cancel coverage 32
 playout-delay nominal 70
 playout-delay minimum low
 playout-delay mode fixed
 no comfort-noise
!
!
!
!
!
dial-peer voice 5006 pots
 description Incoming pattern to match our DID block
 answer-address 57097092..
 destination-pattern 57097092..
 incoming called-number 57097092..
 direct-inward-dial
 port 0/1/0:23
 forward-digits 3
!
dial-peer voice 5005 pots
 description Incoming pattern to match our main number
 answer-address 5707145005
 destination-pattern 5707145005
 incoming called-number 5707145005
 direct-inward-dial
 port 0/1/0:23
 forward-digits 3
!
dial-peer voice 99999 voip
 description  Free 800 calling via freeworlddialup
 translation-profile outgoing 800-To-FWD
 answer-address 18.........
 destination-pattern 18.........
 voice-class codec 1
 session protocol sipv2
 session target dns:fwd.pulver.com
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 1 voip
 description Outbound dial-peer for ISN calling
 answer-address .*T
 destination-pattern .*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 2 voip
 description Outbound dial-peer for ISN calling
 answer-address ..*T
 destination-pattern ..*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 3 voip
 description Outbound dial-peer for ISN calling
 answer-address ...*T
 destination-pattern ...*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 4 voip
 description Outbound dial-peer for ISN calling
 answer-address ....*T
 destination-pattern ....*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 5 voip
 description Outbound dial-peer for ISN calling
 answer-address .....*T
 destination-pattern .....*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 6 voip
 description Outbound dial-peer for ISN calling
 answer-address ......*T
 destination-pattern ......*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 7 voip
 description Outbound dial-peer for ISN calling
 answer-address .......*T
 destination-pattern .......*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 8 voip
 description Outbound dial-peer for ISN calling
 answer-address ........*T
 destination-pattern ........*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 9 voip
 description Outbound dial-peer for ISN calling
 answer-address .........*T
 destination-pattern .........*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 10 voip
 description Outbound dial-peer for ISN calling
 answer-address ..........*T
 destination-pattern ..........*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
dial-peer voice 11 voip
 description Outbound dial-peer for ISN calling
 answer-address ...........*T
 destination-pattern ...........*T
 voice-class codec 1
 session protocol sipv2
 session target sip-server
 dtmf-relay rtp-nte
 no vad
!
!
gateway
 timer receive-rtp 1200
!
sip-ua
 retry invite 3
 retry response 3
 retry bye 3
 retry cancel 3
 retry options 3
 timers expires 300000
 sip-server dns:freenum.org
!
!
!

5.5. Testing Outbound Calling

The following test numbers may be used to verify correct configuration of outbound ISN calling from your domain.

613*262 Free World Dialup echo test.
1234*256 John's annoying screaming monkeys, followed by an echo test.

6. Caller ID

The Caller ID for ISN calls should be a valid SIP URI for the caller. Although this approach lacks symmetry, it at least allows remote systems to understand (but perhaps not use) a valid return path. As an alternate URI method (typically SIP) is the ultimate result of an ISN lookup, using the SIP URI as the Caller ID is the most logical method for assigning a URI. Of course, Caller ID name (e.g "John Doe") is left to the local administrator, as are any privacy flags which may obscure the caller ID in it's entirety.

ISN domains that gateway incoming ISN calls to legacy PBX handsets or cell phones present unique challenges for proper display of Caller ID. Ideally Caller ID should always be presented in a meaningful and usable fashion. Unfortunately, current standards and equipment do not provide a general solution to this problem.


A. External ISN Resolver for SER

#! /usr/bin/perl -w
# isn-resolv.pl
#
# Take URI containing an ISN as first argument and perform ENUM-like
# ISN resolution, returning resulting URI.
#
# Suitable for use in SER (e.g. exec_dset("isn-resolv.pl"))
#
# Written by Ben Teitelbaum, http://people.internet2.edu/~ben/
# Copyright (c) 2005, Internet2
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
#
# * Neither the name of the Internet2 nor the names of its contributors
#   may be used to endorse or promote products derived from this
#   software without explicit prior written permission.
#
# You are under no obligation whatsoever to provide any enhancements to
# Internet2 or its contributors.  If you choose to provide your
# enhancements, or if you choose to otherwise publish or distribute your
# enhancements, in source code form without contemporaneously requiring
# end users to enter into a separate written license agreement for such
# enhancements, then you thereby grant Internet2 and its contributors a
# non-exclusive, royalty-free, perpetual license to install, use,
# modify, prepare derivative works, incorporate into the software or
# other computer software, distribute, and sublicense your enhancements
# or derivative works thereof, in binary and source code form.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND WITH ALL FAULTS.  ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
# NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY
# QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.  IN NO
# EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS, OR THE UNIVERSITY
# CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# If Net::DNS is missing from your Perl installation, you must install
# it before using this script.  Here are a few ways to grab it:
#
# Web: http://www.net-dns.org/download/
# Debian: [sudo] apt-get install libnet-dns-perl
# Red Hat: [sudo] up2date -i perl-Net-DNS
# CPAN: [sudo] cpan -i Net::DNS
use Net::DNS;
use strict;

#
# Make sure that $isn_root is set correctly.
my $isn_root = 'freenum.org';
my $log = '/tmp/isn.log';

$\ = "\n";

my $res = Net::DNS::Resolver->new;
my $uri;

sub enumize_uri($) {
    my $isn = shift;

    # Extract ISN from given URI, exiting if URI doesn't contain one
    $isn =~ s/^(sip:)?([0-9]*\*[0-9]+)\@?[^\@]*/$2/ || die("Invalid input: $isn (URI must contain a valid ISN)");
    my ($num, $itad) = split(/\*/, $isn);

    return join('.', reverse(split(/ */, $num))) . ".$itad.$isn_root";
}

#
# URI to process is first ARG
$_ = shift;
chomp;
$uri = $_;

$uri =~ s/(sip:)?([0-9]*\*[0-9]+)/$2/;
my $dname = &enumize_uri($uri);

my $query = $res->query($dname, 'NAPTR') || exit;

# Apply ENUM-style NAPTR algorithm
#
# Strip out non-matching services and record types and any rule with a
# flag other than "U"; then sort by order, preference
my @rr =
    sort {$a->order <=> $b->order || $a->preference <=> $b->preference }
grep {$_->type =~ /NAPTR/ && $_->service =~ /^E2U/ && $_->flags =~ /^U$/i} $query->answer;

# Loop through rules until a match is found
foreach my $rule (@rr) {
    my $subst_regexp = $rule->regexp;

    # FIXME: NAPTR uses POSIX extended regular expressions, which are
    # different from Perl's.  I don't understand all the differences,
    # but one difference is that @ needs to be escaped.
    $subst_regexp =~ s/\@/\\\@/g;

    my($nothin, $regexp, $replacement) = split(/\!/, $subst_regexp);

    # Backrefs (e.g. \1, \2) won't be available in eval'd assignment
    # below, so convert to Perl's $1-$9 match variables.  Note that
    # per RFC2915, POSIX ERE backrefs only go up to \9.
    $replacement =~ s/\\([1-9])/\$$1/g;

    if ($uri =~ $regexp) {
        eval("\$uri = \"$replacement\"");
        print $uri;
        exit(0);
    }
}

exit(1);

B. Authors

John Todd <jtodd@loligo.com>,