README.enum 15 KB

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