9a3384d4631a6d50a2b9725f8a7a11496a4bc856
[asterisk/asterisk.git] / doc / tex / enum.tex
1 \section{The ENUMLOOKUP dialplan function}
2
3 The ENUMLOOKUP function is more complex than it first may appear, and
4 this guide is to give a general overview and set of examples that may
5 be well-suited for the advanced user to evaluate in their
6 consideration of ENUM or ENUM-like lookup strategies.  This document
7 assumes a familiarity with ENUM (RFC3761) or ENUM-like methods, as
8 well as familiarity with NAPTR DNS records (RFC2915, RFC3401-3404).
9 For an overview of NAPTR records, and the use of NAPTRs in the ENUM
10 global phone-number-to-DNS mapping scheme, please see
11 \url{http://www.voip-info.org/tiki-index.php?page=ENUM} for more detail.
12
13 Using ENUM within Asterisk can be simple or complex, depending on how
14 many failover methods and redundancy procedures you wish to utilize.
15 Implementation of ENUM paths is supposedly defined by the person
16 creating the NAPTR records, but the local administrator may choose to
17 ignore certain NAPTR response methods (URI types) or prefer some over
18 others, which is in contradiction to the RFC.  The ENUMLOOKUP method
19 simply provides administrators a method for determining NAPTR results
20 in either the globally unique ENUM (e164.arpa) DNS tree, or in other
21 ENUM-like DNS trees which are not globally unique.  The methods to
22 actually create channels ("dial") results given by the ENUMLOOKUP
23 function is then up to the administrator to implement in a way that
24 best suits their environment.
25
26 \begin{verbatim}
27 Function: ENUMLOOKUP(number[,Method-type[,options[,record#[,zone-suffix]]]])
28 \end{verbatim}
29
30   Performs an ENUM tree lookup on the specified number, method type, and
31   ordinal record offset, and returns one of four different values:
32
33 \begin{enumerate}
34    \item post-parsed NAPTR of one method (URI) type
35    \item count of elements of one method (URI) type
36    \item count of all method types
37    \item full URI of method at a particular point in the list of all possible methods
38 \end{enumerate}
39
40 \subsection{Arguments}
41
42 \begin{itemize}
43   \item number
44   \begin{itemize}
45     \item telephone number or search string.  Only numeric values
46     within this string are parsed; all other digits are ignored for
47     search, but are re-written during NAPTR regexp expansion.
48   \end{itemize}
49
50   \item service\_type
51   \begin{itemize}
52      \item tel, sip, h323, iax2, mailto, ...[any other string],
53      ALL. Default type is "sip".
54      Special name of "ALL" will create a list of method types across
55      all NAPTR records for the search number, and then put the results
56      in an ordinal list starting with 1. The position <number>
57      specified will then be returned, starting with 1 as the first
58      record (lowest value) in the list.  The service types are not
59      hardcoded in Asterisk except for the default (sip) if no other
60      service type specified; any method type string (IANA-approved or
61      not) may be used except for the string "ALL".
62   \end{itemize}
63
64   \item options
65   \begin{itemize}
66     \item c
67     \begin{itemize}
68       \item count. Returns the number of records of this type are returned
69     (regardless of order or priority.)  If "ALL" is the specified
70     service\_type, then a count of all methods will be returned for the
71     DNS record.
72     \end{itemize}
73   \end{itemize}
74
75   \item record\#
76   \begin{itemize}
77     \item which record to present if multiple answers are returned
78     <integer> = The record in priority/order sequence based on the
79     total count of records passed back by the query. If a service\_type
80     is specified, all entries of that type will be sorted into an
81     ordinal list starting with 1 (by order first, then priority).
82     The default of <options> is "1"
83   \end{itemize}
84
85   \item zone\_suffix
86   \begin{itemize}
87     \item allows customization of the ENUM zone. Default is e164.arpa.
88   \end{itemize}
89 \end{itemize}
90
91 \subsection{Examples}
92
93 Let's use this ENUM list as an example (note that these examples exist
94 in the DNS, and will hopefully remain in place as example
95 destinations, but they may change or become invalid over time.  The
96 end result URIs are not guaranteed to actually work, since some of
97 these hostnames or SIP proxies are imaginary.  Of course, the tel:
98 replies go to directory assistance for New York City and San
99 Francisco...)  Also note that the complex SIP NAPTR at weight 30 will
100 strip off the leading "+" from the dialed string if it exists.  This
101 is probably a better NAPTR than hard-coding the number into the NAPTR,
102 and it is included as a more complex regexp example, though other
103 simpler NAPTRs will work just as well.
104
105 \begin{verbatim}
106 0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 10 100 "u"
107      "E2U+tel" "!^\\+13015611020$!tel:+12125551212!" .
108 0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 21 100 "u"
109      "E2U+tel" "!^\\+13015611020$!tel:+14155551212!" .
110 0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 25 100 "u"
111      "E2U+sip" "!^\\+13015611020$!sip:2203@sip.fox-den.com!" .
112 0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 26 100 "u"
113      "E2U+sip" "!^\\+13015611020$!sip:1234@sip-2.fox-den.com!" .
114 0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 30 100 "u"
115      "E2U+sip" "!^\\+*([^\\*]*)!sip:\\1@sip-3.fox-den.com!" .
116 0.2.0.1.1.6.5.1.0.3.1.loligo.com. 3600 IN NAPTR 55 100 "u"
117      "E2U+mailto" "!^\\+13015611020$!mailto:jtodd@fox-den.com!" .
118 \end{verbatim}
119
120 Example 1: Simplest case, using first SIP return (use all defaults
121 except for domain name)
122 \begin{verbatim}
123 exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,,,,loligo.com)})
124   returns: ${foo}="2203@sip.fox-den.com"
125 \end{verbatim}
126
127 Example 2: What is the first "tel" pointer type for this number?
128 (after sorting by order/preference; default of "1" is assumed in
129 options field)
130 \begin{verbatim}
131 exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,tel,,,loligo.com)})
132   returns: ${foo}="+12125551212"
133 \end{verbatim}
134
135 Example 3: How many "sip" pointer type entries are there for this number?
136 \begin{verbatim}
137 exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,sip,c,,loligo.com)})
138   returns: ${foo}=3
139 \end{verbatim}
140
141 Example 4: For all the "tel" pointer type entries, what is the second
142 one in the list? (after sorting by preference)
143 \begin{verbatim}
144 exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,tel,,2,loligo.com)})
145   returns: ${foo}="+14155551212"
146 \end{verbatim}
147
148 Example 5: How many NAPTRs (tel, sip, mailto, etc.) are in the list for this number?
149 \begin{verbatim}
150 exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,ALL,c,,loligo.com)})
151   returns: ${foo}=6
152 \end{verbatim}
153
154 Example 6: Give back the second full URI in the sorted list of all NAPTR URIs:
155 \begin{verbatim}
156 exten => 100,1,Set(foo=${ENUMLOOKUP(+13015611020,ALL,,2,loligo.com)})
157   returns: ${foo}="tel:+14155551212"  [note the "tel:" prefix in the string]
158 \end{verbatim}
159
160 Example 7: Look up first SIP entry for the number in the e164.arpa zone (all defaults)
161 \begin{verbatim}
162 exten => 100,1,Set(foo=${ENUMLOOKUP(+437203001721)})
163   returns: ${foo}="enum-test@sip.nemox.net"  [note: this result is
164   subject to change as it is "live" DNS and not under my control]
165 \end{verbatim}
166
167 Example 8: Look up the ISN mapping in freenum.org alpha test zone
168 \begin{verbatim}
169 exten => 100,1,Set(foo=${ENUMLOOKUP(1234*256,,,,freenum.org)})
170   returns: ${foo}="1234@204.91.156.10"  [note: this result is subject
171   to change as it is "live" DNS]
172 \end{verbatim}
173
174 Example 9: Give back the first SIP pointer for a number in the
175 \begin{verbatim}
176 enum.yoydynelabs.com zone (invalid lookup)
177 exten => 100,1,Set(foo=${ENUMLOOKUP(1234567890,sip,,1,enum.yoyodynelabs.com)})
178   returns: ${foo}=""
179 \end{verbatim}
180
181 \subsection{Usage notes and subtle features}
182 \begin{itemize}
183   \item The use of "+" in lookups is confusing, and warrants further
184   explanation.  All E.164 numbers ("global phone numbers") by
185   definition need a leading "+" during ENUM lookup.  If you neglect to
186   add a leading "+", you may discover that numbers that seem to exist
187   in the DNS aren't getting matched by the system or are returned with
188   a null string result.  This is due to the NAPTR reply requiring a
189   "+" in the regular expression matching sequence.  Older versions of
190   Asterisk add a "+" from within the code, which may confuse
191   administrators converting to the new function.  Please ensure that
192   all ENUM (e164.arpa) lookups contain a leading "+" before lookup, so
193   ensure your lookup includes the leading plus sign.  Other DNS trees
194   may or may not require a leading "+" - check before using those
195   trees, as it is possible the parsed NAPTRs will not provide correct
196   results unless you have the correct dialed string.  If you get
197   console messages like "WARNING[24907]: enum.c:222 parse\_naptr: NAPTR
198   Regex match failed." then it is very possible that the returned
199   NAPTR expects a leading "+" in the search string (or the returned
200   NAPTR is mis-formed.)
201
202   \item If a query is performed of type "c" ("count") and let's say you
203   get back 5 records and then some seconds later a query is made
204   against record 5 in the list, it may not be the case that the DNS
205   resolver has the same answers as it did a second or two ago - maybe
206   there are only 4 records in the list in the newest query.  The
207   resolver should be the canonical storage location for DNS records,
208   since that is the intent of ENUM.  However, some obscure future
209   cases may have wildly changing NAPTR records within several seconds.
210   This is a corner case, and probably only worth noting as a very rare
211   circumstance. (note: I do not object to Asterisk's dnsmgr method of
212   locally caching DNS replies, but this method needs to honor the TTL
213   given by the remote zone master.  Currently, the ENUMLOOKUP function
214   does not use the dnsmgr method of caching local DNS replies.)
215
216   \item If you want strict NAPTR value ordering, then it will be
217   necessary to use the "ALL" method to incrementally step through the
218   different returned NAPTR pointers.  You will need to use string
219   manipulation to strip off the returned method types, since the
220   results will look like "sip:12125551212" in the returned value.
221   This is a non-trivial task, though it is required in order to have
222   strict RFC compliance and to comply with the desires of the remote
223   party who is presenting NAPTRs in a particular order for a reason.
224
225   \item Default behavior for the function (even in event of an error) is
226   to move to the next priority, and the result is a null value.  Most
227   ENUM lookups are going to be failures, and it is the responsibility
228   of the dialplan administrator to manage error conditions within
229   their dialplan.  This is a change from the old app\_enumlookup method
230   and it's arbitrary priority jumping based on result type or failure.
231
232   \item Anything other than digits will be ignored in lookup strings.
233   Example: a search string of "+4372030blah01721" will turn into
234   1.2.7.1.0.0.3.0.2.7.3.4.e164.arpa. for the lookup.  The NAPTR
235   parsing may cause unexpected results if there are strings inside
236   your NAPTR lookups.
237
238   \item If there exist multiple records with the same weight and order as
239   a result of your query, the function will RANDOMLY select a single
240   NAPTR from those equal results.
241
242   \item Currently, the function ignores the settings in enum.conf as the
243   search zone name is now specified within the function, and the H323
244   driver can be chosen by the user via the dialplan.  There were no
245   other values in this file, and so it becomes deprecated.
246
247   \item The function will digest and return NAPTRs which use older
248   (deprecated) style, reversed method strings such as "sip+E2U"
249   instead of the more modern "E2U+sip"
250
251   \item There is no provision for multi-part methods at this time.  If
252   there are multiple NAPTRs with (as an example) a method of
253   "E2U+voice:sip" and then another NAPTR in the same DNS record with a
254   method of ""E2U+sip", the system will treat these both as method
255   "sip" and they will be separate records from the perspective of the
256   function.  Of course, if both records point to the same URI and have
257   equal priority/weight (as is often the case) then this will cause no
258   serious difficulty, but it bears mentioning.
259
260   \item ISN (ITAD Subscriber Number) usage:  If the search number is of
261   the form ABC*DEF (where ABC and DEF are at least one numeric digit)
262   then perform an ISN-style lookup where the lookup is manipulated to
263   C.B.A.DEF.domain.tld (all other settings and options apply.)  See
264   \url{http://www.freenum.org/} for more details on ISN lookups.  In the
265   unlikely event you wish to avoid ISN re-writes, put an "n" as the
266   first digit of the search string - the "n" will be ignored for the search.
267 \end{itemize}
268
269 \subsection{Some more Examples}
270
271 All examples below except where noted use "e164.arpa" as the
272 referenced domain, which is the default domain name for ENUMLOOKUP.
273 All numbers are assumed to not have a leading "+" as dialed by the
274 inbound channel, so that character is added where necessary during
275 ENUMLOOKUP function calls.
276
277 \begin{astlisting}
278 \begin{verbatim}
279 ; example 1
280 ;
281 ; Assumes North American international dialing (011) prefix.
282 ; Look up the first SIP result and send the call there, otherwise
283 ;  send the call out a PRI.  This is the most simple possible
284 ;  ENUM example, but only uses the first SIP reply in the list of
285 ;  NAPTR(s).
286 ;
287 exten => _011.,1,Set(enumresult=${ENUMLOOKUP(+${EXTEN:3})})
288 exten => _011.,n,Dial(SIP/${enumresult})
289 exten => _011.,n,Dial(Zap/g1/${EXTEN})
290 ;
291 ; end example 1
292
293 ; example 2
294 ;
295 ; Assumes North American international dialing (011) prefix.
296 ; Check to see if there are multiple SIP NAPTRs returned by
297 ;  the lookup, and dial each in order.  If none work (or none
298 ;  exist) then send the call out a PRI, group 1.
299 ;
300 exten => _011.,1,Set(sipcount=${ENUMLOOKUP(${EXTEN:3},sip,c)}|counter=0)
301 exten => _011.,n,While($["${counter}"<"${sipcount}"])
302 exten => _011.,n,Set(counter=$[${counter}+1])
303 exten => _011.,n,Dial(SIP/${ENUMLOOKUP(+${EXTEN:3},sip,,${counter})})
304 exten => _011.,n,EndWhile
305 exten => _011.,n,Dial(Zap/g1/${EXTEN})
306 ;
307 ; end example 2
308
309 ; example 3
310 ;
311 ; This example expects an ${EXTEN} that is an e.164 number (like
312 ;  14102241145 or 437203001721)
313 ; Search through e164.arpa and then also search through e164.org
314 ;  to see if there are any valid SIP or IAX termination capabilities.
315 ;  If none, send call out via Zap channel 1.
316 ;
317 ; Start first with e164.arpa zone...
318 ;
319 exten => _X.,1,Set(sipcount=${ENUMLOOKUP(+${EXTEN},sip,c)}|counter=0)
320 exten => _X.,2,GotoIf($["${counter}"<"${sipcount}"]?3:6)
321 exten => _X.,3,Set(counter=$[${counter}+1])
322 exten => _X.,4,Dial(SIP/${ENUMLOOKUP(+${EXTEN},sip,,${counter})})
323 exten => _X.,5,GotoIf($["${counter}"<"${sipcount}"]?3:6)
324 ;
325 exten => _X.,6,Set(iaxcount=${ENUMLOOKUP(+${EXTEN},iax2,c)}|counter=0)
326 exten => _X.,7,GotoIf($["${counter}"<"${iaxcount}"]?8:11)
327 exten => _X.,8,Set(counter=$[${counter}+1])
328 exten => _X.,9,Dial(IAX2/${ENUMLOOKUP(+${EXTEN},iax2,,${counter})})
329 exten => _X.,10,GotoIf($["${counter}"<"${iaxcount}"]?8:11)
330 ;
331 exten => _X.,11,NoOp("No valid entries in e164.arpa for ${EXTEN} - checking in e164.org")
332 ;
333 ; ...then also try e164.org, and look for SIP and IAX NAPTRs...
334 ;
335 exten => _X.,12,Set(sipcount=${ENUMLOOKUP(+${EXTEN},sip,c,,e164.org)}|counter=0)
336 exten => _X.,13,GotoIf($["${counter}"<"${sipcount}"]?14:17)
337 exten => _X.,14,Set(counter=$[${counter}+1])
338 exten => _X.,15,Dial(SIP/${ENUMLOOKUP(+${EXTEN},sip,,${counter},e164.org)})
339 exten => _X.,16,GotoIf($["${counter}"<"${sipcount}"]?14:17)
340 ;
341 exten => _X.,17,Set(iaxcount=${ENUMLOOKUP(+${EXTEN},iax2,c,,e164.org)}|counter=0)
342 exten => _X.,18,GotoIf($["${counter}"<"${iaxcount}"]?19:22)
343 exten => _X.,19,Set(counter=$[${counter}+1])
344 exten => _X.,20,Dial(IAX2/${ENUMLOOKUP(+${EXTEN},iax2,,${counter},e164.org)})
345 exten => _X.,21,GotoIf($["${counter}"<"${iaxcount}"]?19:22)
346 ;
347 ; ...then send out PRI.
348 ;
349 exten => _X.,22,NoOp("No valid entries in e164.org for ${EXTEN} - sending out via Zap")
350 exten => _X.,23,Dial(Zap/g1/${EXTEN})
351 ;
352 ; end example 3
353
354 \end{verbatim}
355 \end{astlisting}