Import unmodified vendor sources for correction and improvement.

Mon, 18 Jan 2010 19:47:23 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 18 Jan 2010 19:47:23 +0100
changeset 12
a3ac912f2857
parent 11
e1a27284134f
child 13
b63f281afe6b

Import unmodified vendor sources for correction and improvement.

opensips/modules/enum/README file | annotate | diff | comparison | revisions
opensips/modules/enum/doc/enum.xml file | annotate | diff | comparison | revisions
opensips/modules/enum/doc/enum_admin.xml file | annotate | diff | comparison | revisions
opensips/modules/enum/enum.c file | annotate | diff | comparison | revisions
opensips/modules/enum/enum.h file | annotate | diff | comparison | revisions
opensips/modules/enum/enum_mod.c file | annotate | diff | comparison | revisions
opensips/modules/enum/enum_mod.h file | annotate | diff | comparison | revisions
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/opensips/modules/enum/README	Mon Jan 18 19:47:23 2010 +0100
     1.3 @@ -0,0 +1,311 @@
     1.4 +Enum Module
     1.5 +
     1.6 +Juha Heinanen
     1.7 +
     1.8 +   <jh@song.fi>
     1.9 +
    1.10 +Otmar Lendl
    1.11 +
    1.12 +   <lendl@nic.at>
    1.13 +
    1.14 +   Copyright © 2002, 2003 Juha Heinanen
    1.15 +   Revision History
    1.16 +   Revision $Revision: 5906 $ $Date: 2009-07-21 10:45:05 +0300
    1.17 +                              (Tue, 21 Jul 2009) $
    1.18 +     __________________________________________________________
    1.19 +
    1.20 +   Table of Contents
    1.21 +
    1.22 +   1. Admin Guide
    1.23 +
    1.24 +        1.1. Overview
    1.25 +        1.2. Dependencies
    1.26 +        1.3. Exported Parameters
    1.27 +
    1.28 +              1.3.1. domain_suffix (string)
    1.29 +              1.3.2. tel_uri_params (string)
    1.30 +              1.3.3. i_enum_suffix (string)
    1.31 +              1.3.4. branchlabel (string)
    1.32 +              1.3.5. bl_algorithm (string)
    1.33 +
    1.34 +        1.4. Exported Functions
    1.35 +
    1.36 +              1.4.1. enum_query(["suffix"[,"service"]])
    1.37 +              1.4.2. enum_pv_query("pvar"[,"suffix"[,"service"]])
    1.38 +              1.4.3. i_enum_query(["suffix"[,"service"]])
    1.39 +              1.4.4. is_from_user_enum()
    1.40 +
    1.41 +   List of Examples
    1.42 +
    1.43 +   1.1. Setting domain_suffix module parameter
    1.44 +   1.2. Setting tel_uri_params module parameter
    1.45 +   1.3. Setting i_enum_suffix module parameter
    1.46 +   1.4. Setting brachlabel module parameter
    1.47 +   1.5. Zone file example
    1.48 +   1.6. Zone file example
    1.49 +   1.7. Setting the bl_algorithm module parameter
    1.50 +   1.8. enum_query usage
    1.51 +   1.9. enum_pv_query usage
    1.52 +   1.10. is_from_user_enum usage
    1.53 +
    1.54 +Chapter 1. Admin Guide
    1.55 +
    1.56 +1.1. Overview
    1.57 +
    1.58 +   Enum module implements [i_]enum_query functions that make an
    1.59 +   enum query based on the user part of the current Request-URI.
    1.60 +   These functions assume that the user part consists of an
    1.61 +   international phone number of the form +decimal-digits, where
    1.62 +   the number of digits is at least 2 and at most 15. Out of this
    1.63 +   number enum_query forms a domain name, where the digits are in
    1.64 +   reverse order and separated by dots followed by domain suffix
    1.65 +   that by default is "e164.arpa.". For example, if the user part
    1.66 +   is +35831234567, the domain name will be
    1.67 +   "7.6.5.4.3.2.1.3.8.5.3.e164.arpa.". i_enum_query operates in a
    1.68 +   similar fashion. The only difference is that it adds a label
    1.69 +   (default "i") to branch off from the default, user-ENUM tree to
    1.70 +   an infrastructure ENUM tree.
    1.71 +
    1.72 +   After forming the domain name, enum_query queries DNS for its
    1.73 +   NAPTR records. From the possible response enum_query chooses
    1.74 +   those records, whose flags field has string value "u", and
    1.75 +   whose services field has string value "e2u+[service:]sip" or
    1.76 +   "e2u+type[:subtype][+type[:subtype]...]" (case is ignored in
    1.77 +   both cases), and whose regexp field is of the form
    1.78 +   !pattern!replacement!.
    1.79 +
    1.80 +   Then enum_query sorts the chosen NAPTR records based on their
    1.81 +   <order, preference>. After sorting, enum_query replaces the
    1.82 +   current Request URI by applying regexp of the most preferred
    1.83 +   NAPTR record its user part and appends to the request new
    1.84 +   branches by applying regexp of each remaining NAPTR record to
    1.85 +   the user part of the current Request URI. If a new URI is a tel
    1.86 +   URI, enum_query appends to it as tel URI parameters the value
    1.87 +   of tel_uri_params module parameter. Finally, enum_query
    1.88 +   associates a q value with each new URI based on the <order,
    1.89 +   preference> of the corresponding NAPTR record.
    1.90 +
    1.91 +   When using enum_query without any parameters, it searches for
    1.92 +   NAPTRs with service type "e2u+sip" in the default enum tree.
    1.93 +   When using enum_query with a single parameter, this parameter
    1.94 +   will be used as enum tree. When using enum_query with two
    1.95 +   parameters, the functionality depends on the first letter in
    1.96 +   the second parameter. When the first letter is not a '+' sign,
    1.97 +   the second parameter will be used to search for NAPTRs with
    1.98 +   service type "e2u+parameter:sip". When the second parameter
    1.99 +   starts with a '+' sign, the ENUM lookup also supports compound
   1.100 +   NAPTRs (e.g. "e2u+voice:sip+video:sip") and searching for
   1.101 +   multiple service types within one lookup. Multiple service
   1.102 +   types must be separeted by a '+' sign.
   1.103 +
   1.104 +   Most of the time you want to route based on the RURI. On rare
   1.105 +   occasions you may wish to route based on something else. The
   1.106 +   function enum_pv_query mimics the behavior of the enum_query
   1.107 +   function except the E.164 number in its pseudo variable
   1.108 +   argument is used for the enum lookup instead of the user part
   1.109 +   of the RURI. Obviously the user part of the RURI is still used
   1.110 +   in the NAPTR regexp.
   1.111 +
   1.112 +   Enum query returns 1 if the current Request URI was replaced
   1.113 +   and -1 if not.
   1.114 +
   1.115 +   Enum module also implements is_from_user_enum function. This
   1.116 +   function does an enum lookup on the from user and returns true
   1.117 +   if found, false otherwise.
   1.118 +
   1.119 +1.2. Dependencies
   1.120 +
   1.121 +   The module depends on the following modules (in the other words
   1.122 +   the listed modules must be loaded before this module):
   1.123 +     * No dependencies.
   1.124 +
   1.125 +1.3. Exported Parameters
   1.126 +
   1.127 +1.3.1. domain_suffix (string)
   1.128 +
   1.129 +   The domain suffix to be added to the domain name obtained from
   1.130 +   the digits of an E164 number. Can be overridden by a parameter
   1.131 +   to enum_query.
   1.132 +
   1.133 +   Default value is "e164.arpa."
   1.134 +
   1.135 +   Example 1.1. Setting domain_suffix module parameter
   1.136 +modparam("enum", "domain_suffix", "e1234.arpa.")
   1.137 +
   1.138 +1.3.2. tel_uri_params (string)
   1.139 +
   1.140 +   A string whose contents is appended to each new tel URI in the
   1.141 +   request as tel URI parameters.
   1.142 +
   1.143 +Note
   1.144 +
   1.145 +   Currently OpenSIPS does not support tel URIs. This means that
   1.146 +   at present tel_uri_params is appended as URI parameters to
   1.147 +   every URI.
   1.148 +
   1.149 +   Default value is ""
   1.150 +
   1.151 +   Example 1.2. Setting tel_uri_params module parameter
   1.152 +modparam("enum", "tel_uri_params", ";npdi")
   1.153 +
   1.154 +1.3.3. i_enum_suffix (string)
   1.155 +
   1.156 +   The domain suffix to be used for i_enum_query() lookups. Can be
   1.157 +   overridden by a parameter to i_enum_query.
   1.158 +
   1.159 +   Default value is "e164.arpa."
   1.160 +
   1.161 +   Example 1.3. Setting i_enum_suffix module parameter
   1.162 +modparam("enum", "i_enum_suffix", "e1234.arpa.")
   1.163 +
   1.164 +1.3.4. branchlabel (string)
   1.165 +
   1.166 +   This parameter determines which label i_enum_query() will use
   1.167 +   to branch off to the infrastructure ENUM tree.
   1.168 +
   1.169 +   Default value is ""i""
   1.170 +
   1.171 +   Example 1.4. Setting brachlabel module parameter
   1.172 +modparam("enum", "branchlabel", "i")
   1.173 +
   1.174 +1.3.5. bl_algorithm (string)
   1.175 +
   1.176 +   This parameter determines which algorithm i_enum_query() will
   1.177 +   use to select the position in the DNS tree where the
   1.178 +   infrastructure tree branches off the user ENUM tree.
   1.179 +
   1.180 +   If set to "cc", i_enum_query() will always inserts the label at
   1.181 +   the country-code level. Examples: i.1.e164.arpa,
   1.182 +   i.3.4.e164.arpa, i.2.5.3.e164.arpa
   1.183 +
   1.184 +   If set to "txt", i_enum_query() will look for a TXT record at
   1.185 +   [branchlabel].[reverse-country-code].[i_enum_suffix] to
   1.186 +   indicate after how many digits the label should in inserted.
   1.187 +
   1.188 +   Example 1.5. Zone file example
   1.189 +i.1.e164.arpa.                     IN TXT   "4"
   1.190 +9.9.9.8.7.6.5.i.4.3.2.1.e164.arpa. IN NAPTR "NAPTR content for  +1 234 5
   1.191 +678 999"
   1.192 +
   1.193 +   If set to "ebl", i_enum_query() will look for an EBL (ENUM
   1.194 +   Branch Label) record at
   1.195 +   [branchlabel].[reverse-country-code].[i_enum_suffix]. See
   1.196 +   http://www.ietf.org/internet-drafts/draft-lendl-enum-branch-loc
   1.197 +   ation-record-00.txt for a description of that record and the
   1.198 +   meaning of the fields. The RR type for the EBL has not been
   1.199 +   allocated yet. This version of the code uses 65300. See
   1.200 +   resolve.h.
   1.201 +
   1.202 +   Example 1.6. Zone file example
   1.203 +i.1.e164.arpa.     TYPE65300  \# 14 (
   1.204 +                              04    ; position
   1.205 +                              01 69 ; separator
   1.206 +                              04 65 31 36 34 04 61 72 70 61 00 ; e164.ar
   1.207 +pa
   1.208 +;                               )
   1.209 +9.9.9.8.7.6.5.i.4.3.2.1.e164.arpa. IN NAPTR "NAPTR content for  +1 234 5
   1.210 +678 999"
   1.211 +
   1.212 +   Default value is "cc"
   1.213 +
   1.214 +   Example 1.7. Setting the bl_algorithm module parameter
   1.215 +modparam("enum", "bl_algorithm", "txt")
   1.216 +
   1.217 +1.4. Exported Functions
   1.218 +
   1.219 +1.4.1.  enum_query(["suffix"[,"service"]])
   1.220 +
   1.221 +   The function performs an enum query and rewrites the
   1.222 +   Request-URI with the result of the query. See Section 1.1,
   1.223 +   "Overview" for more information.
   1.224 +
   1.225 +   Meaning of the parameters is as follows:
   1.226 +     * suffix - Suffix to be appended to the domain name.
   1.227 +     * service - Service string to be used in the service field.
   1.228 +
   1.229 +   This function can be used from REQUEST_ROUTE.
   1.230 +
   1.231 +   Example 1.8. enum_query usage
   1.232 +...
   1.233 +# search for "e2u+sip" in freenum.org
   1.234 +enum_query("freenum.org.");
   1.235 +...
   1.236 +# search for "e2u+sip" in default tree (configured as parameter)
   1.237 +enum_query();
   1.238 +...
   1.239 +# search for "e2u+voice:sip" in e164.arpa
   1.240 +enum_query("e164.arpa.","voice");
   1.241 +...
   1.242 +# search for service type "sip" or "voice:sip" or "video:sip"
   1.243 +# note the '+' sign in front of the second parameter
   1.244 +enum_query("e164.arpa.","+sip+voice:sip+video:sip");
   1.245 +...
   1.246 +# quering for service sip and voice:sip
   1.247 +enum_query("e164.arpa.");
   1.248 +enum_query("e164.arpa.","voice");
   1.249 +# or use instead
   1.250 +enum_query("e164.arpa.","+sip+voice:sip");
   1.251 +...
   1.252 +
   1.253 +1.4.2.  enum_pv_query("pvar"[,"suffix"[,"service"]])
   1.254 +
   1.255 +   The function performs an enum query on E.164 number stored in
   1.256 +   its pseudo variable argument and rewrites the Request-URI with
   1.257 +   the result of the query. See Section 1.1, "Overview" for more
   1.258 +   information.
   1.259 +
   1.260 +   Meaning of the parameters is as follows:
   1.261 +     * pvar - Pseudo variable that holds an E.164 number on which
   1.262 +       enum query is performed.
   1.263 +     * suffix - Suffix to be appended to the domain name.
   1.264 +     * service - Service string to be used in the service field.
   1.265 +
   1.266 +   This function can be used from REQUEST_ROUTE.
   1.267 +
   1.268 +   Example 1.9. enum_pv_query usage
   1.269 +...
   1.270 +# search for "e2u+sip" in freenum.org
   1.271 +enum_pv_query("$avp(i:100)", "freenum.org.");
   1.272 +...
   1.273 +# search for "e2u+sip" in default tree (configured as parameter)
   1.274 +enum_pv_query("$fU");
   1.275 +...
   1.276 +# search for "e2u+voice:sip" in e164.arpa
   1.277 +enum_pv_query("$avp(i:100)","e164.arpa.","voice");
   1.278 +...
   1.279 +# search for service type "sip" or "voice:sip" or "video:sip"
   1.280 +# note the '+' sign in front of the second parameter
   1.281 +enum_pv_query("$fU","e164.arpa.","+sip+voice:sip+video:sip");
   1.282 +...
   1.283 +# quering for service sip and voice:sip
   1.284 +enum_pv_query("$avp(i:100)","e164.arpa.");
   1.285 +enum_pv_query("$avp(i:100)","e164.arpa.","voice");
   1.286 +# or use instead
   1.287 +enum_pv_query("$avp(i:100)","e164.arpa.","+sip+voice:sip");
   1.288 +...
   1.289 +
   1.290 +1.4.3.  i_enum_query(["suffix"[,"service"]])
   1.291 +
   1.292 +   The function performs an enum query and rewrites the
   1.293 +   Request-URI with the result of the query. This the
   1.294 +   Infrastructure-ENUM version of enum_query(). The only
   1.295 +   difference to enum_query() is in the calculation of the FQDN
   1.296 +   where NAPTR records are looked for.
   1.297 +
   1.298 +   See
   1.299 +   ftp://ftp.rfc-editor.org/in-notes/internet-drafts/draft-haberle
   1.300 +   r-carrier-enum-01.txt for the rationale behind this function.
   1.301 +
   1.302 +1.4.4. is_from_user_enum()
   1.303 +
   1.304 +   Checks if the user part of from URI is found in an enum lookup.
   1.305 +   Returns 1 if yes and -1 if not.
   1.306 +
   1.307 +   This function can be used from REQUEST_ROUTE.
   1.308 +
   1.309 +   Example 1.10. is_from_user_enum usage
   1.310 +...
   1.311 +if (is_from_user_enum()) {
   1.312 +        ....
   1.313 +};
   1.314 +...
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/opensips/modules/enum/doc/enum.xml	Mon Jan 18 19:47:23 2010 +0100
     2.3 @@ -0,0 +1,46 @@
     2.4 +<?xml version="1.0" encoding='ISO-8859-1'?>
     2.5 +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
     2.6 +"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
     2.7 +
     2.8 +<!ENTITY admin SYSTEM "enum_admin.xml">
     2.9 +<!ENTITY faq SYSTEM "../../../doc/module_faq.xml">
    2.10 +
    2.11 +<!-- Include general documentation entities -->
    2.12 +<!ENTITY % docentities SYSTEM "../../../doc/entities.xml">
    2.13 +%docentities;
    2.14 +
    2.15 +]>
    2.16 +
    2.17 +<book>
    2.18 +    <bookinfo>
    2.19 +	<title>Enum Module</title>
    2.20 +	<authorgroup>
    2.21 +	    <author>
    2.22 +		<firstname>Juha</firstname>
    2.23 +		<surname>Heinanen</surname>
    2.24 +		<email>jh@song.fi</email>
    2.25 +	    </author>
    2.26 +	    <author>
    2.27 +		<firstname>Otmar</firstname>
    2.28 +		<surname>Lendl</surname>
    2.29 +		<email>lendl@nic.at</email>
    2.30 +	    </author>
    2.31 +	</authorgroup>
    2.32 +	<copyright>
    2.33 +	    <year>2002</year>
    2.34 +	    <year>2003</year>
    2.35 +	    <holder>Juha Heinanen</holder>
    2.36 +	</copyright>
    2.37 +	<revhistory>
    2.38 +	    <revision>
    2.39 +		<revnumber>$Revision: 5901 $</revnumber>
    2.40 +		<date>$Date: 2009-07-21 10:45:05 +0300 (Tue, 21 Jul 2009) $</date>
    2.41 +	    </revision>
    2.42 +	</revhistory>
    2.43 +    </bookinfo>
    2.44 +    <toc></toc>
    2.45 +    
    2.46 +    &admin;
    2.47 +    &faq;
    2.48 +
    2.49 +</book>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/opensips/modules/enum/doc/enum_admin.xml	Mon Jan 18 19:47:23 2010 +0100
     3.3 @@ -0,0 +1,378 @@
     3.4 +<!-- Enum Module User's Guide -->
     3.5 +
     3.6 +<chapter>
     3.7 +	
     3.8 +	<title>&adminguide;</title>
     3.9 +
    3.10 +	<section id="sec-overview">
    3.11 +	<title>Overview</title>
    3.12 +	<para>
    3.13 +		Enum module implements [i_]enum_query functions that make an enum query 
    3.14 +		based on the user part of the current Request-URI. These functions
    3.15 +		assume that the user part consists of an international phone number 
    3.16 +		of the form +decimal-digits, where the number of digits is at
    3.17 +		least 2 and at most 15. Out of this number 
    3.18 +		<function moreinfo="none">enum_query</function> forms a domain name, 
    3.19 +		where the digits are in reverse order and separated by dots followed by 
    3.20 +		domain suffix that by default is <quote>e164.arpa.</quote>. For example, 
    3.21 +		if the user part is +35831234567, the domain
    3.22 +		name will be <quote>7.6.5.4.3.2.1.3.8.5.3.e164.arpa.</quote>.
    3.23 +		<function moreinfo="none">i_enum_query</function> operates in a similar
    3.24 +		fashion. The only difference is that it adds a label (default "i")
    3.25 +		to branch off from the default, user-ENUM tree to an infrastructure ENUM tree.
    3.26 +	</para>
    3.27 +	<para>
    3.28 +		After forming the domain name, 
    3.29 +		<function moreinfo="none">enum_query</function> queries
    3.30 +		DNS for its NAPTR records. From the possible response 
    3.31 +		<function moreinfo="none">enum_query</function> chooses those records, 
    3.32 +		whose flags field has string value "u", and whose services field has 
    3.33 +		string value "e2u+[service:]sip" or 
    3.34 +		"e2u+type[:subtype][+type[:subtype]...]" (case is ignored in both 
    3.35 +		cases), and whose regexp field is of the form !pattern!replacement!.
    3.36 +	</para>
    3.37 +	<para>
    3.38 +		Then <function moreinfo="none">enum_query</function> sorts the chosen 
    3.39 +		NAPTR records based on their &lt;order, preference&gt;.  After sorting, 
    3.40 +		<function moreinfo="none">enum_query</function> replaces the current 
    3.41 +		Request URI by applying regexp of the most preferred NAPTR record its 
    3.42 +		user part and appends to the request new branches by applying regexp of 
    3.43 +		each remaining NAPTR record to the user part of the
    3.44 +		current Request URI. If a new URI is a tel URI, 
    3.45 +		<function moreinfo="none">enum_query</function> appends to it as tel 
    3.46 +		URI parameters the value of tel_uri_params module parameter. Finally, 
    3.47 +		<function moreinfo="none">enum_query</function> associates a q value 
    3.48 +		with each new URI based on the &lt;order, preference&gt; of the 
    3.49 +		corresponding NAPTR record.
    3.50 +	</para>
    3.51 +	<para>
    3.52 +		When using <function moreinfo="none">enum_query</function> without any 
    3.53 +		parameters, it searches for NAPTRs with service type "e2u+sip" in the 
    3.54 +		default enum tree. When using 
    3.55 +		<function moreinfo="none">enum_query</function> with a single parameter, 
    3.56 +		this parameter will be used as enum tree. When using 
    3.57 +		<function moreinfo="none">enum_query</function> 
    3.58 +		with two parameters, the functionality depends on the first letter in 
    3.59 +		the second parameter. When the first letter is not a '+' sign, the 
    3.60 +		second parameter will be used to search for NAPTRs with service type 
    3.61 +		"e2u+parameter:sip". When the second parameter starts with a '+' sign, 
    3.62 +		the ENUM lookup also supports compound NAPTRs 
    3.63 +		(e.g. "e2u+voice:sip+video:sip") and searching for multiple service 
    3.64 +		types within one lookup. Multiple service types must be separeted 
    3.65 +		by a '+' sign.
    3.66 +	</para>
    3.67 +	<para>
    3.68 +		Most of the time you want to route based on the RURI.  On rare occasions
    3.69 +		you may wish to route based on something else. The function
    3.70 +		<function moreinfo="none">enum_pv_query</function> mimics the behavior
    3.71 +		of the <function moreinfo="none">enum_query</function> function except the
    3.72 +		E.164 number in its pseudo variable argument is used for the enum lookup instead of the user
    3.73 +		part of the RURI.  Obviously the user part of the RURI is still used in the
    3.74 +		NAPTR regexp.
    3.75 +	</para>
    3.76 +	<para>
    3.77 +		Enum query returns 1 if the current Request URI was replaced 
    3.78 +		and -1 if not.
    3.79 +	</para>
    3.80 +	<para>
    3.81 +		Enum module also implements is_from_user_enum function.
    3.82 +		This function does an enum lookup on the from user and
    3.83 +		returns true if found, false otherwise.
    3.84 +	</para>
    3.85 +	</section>
    3.86 +
    3.87 +	<section>
    3.88 +	<title>Dependencies</title>
    3.89 +	<para>
    3.90 +		The module depends on the following modules (in the other words the 
    3.91 +		listed modules must be loaded before this module):
    3.92 +		<itemizedlist>
    3.93 +		<listitem>
    3.94 +			<para>No dependencies.</para>
    3.95 +		</listitem>
    3.96 +		</itemizedlist>
    3.97 +	</para>
    3.98 +	</section>
    3.99 +
   3.100 +	<section>
   3.101 +	<title>Exported Parameters</title>
   3.102 +	<section>
   3.103 +		<title><varname>domain_suffix</varname> (string)</title>
   3.104 +		<para>
   3.105 +		The domain suffix to be added to the domain name obtained from
   3.106 +		the digits of an <acronym>E164</acronym> number. Can be overridden 
   3.107 +		by a parameter to enum_query.
   3.108 +		</para>
   3.109 +		<para>
   3.110 +		Default value is <quote>e164.arpa.</quote>
   3.111 +		</para>
   3.112 +		<example>
   3.113 +		<title>Setting domain_suffix module parameter</title>
   3.114 +		<programlisting format="linespecific">
   3.115 +modparam("enum", "domain_suffix", "e1234.arpa.")
   3.116 +</programlisting>
   3.117 +		</example>
   3.118 +	</section>
   3.119 +
   3.120 +	<section>
   3.121 +		<title><varname>tel_uri_params</varname> (string)</title>
   3.122 +		<para>
   3.123 +		A string whose contents is appended to each new tel URI in the 
   3.124 +		request as tel URI parameters.
   3.125 +		</para>
   3.126 +		<note>
   3.127 +		<para>
   3.128 +			Currently &osips; does not support tel URIs. This means that at present
   3.129 +			tel_uri_params is appended as URI parameters to every URI.
   3.130 +		</para>
   3.131 +		</note>
   3.132 +		<para>
   3.133 +		Default value is <quote></quote>
   3.134 +		</para>
   3.135 +		<example>
   3.136 +		<title>Setting tel_uri_params module parameter</title>
   3.137 +		<programlisting format="linespecific">
   3.138 +modparam("enum", "tel_uri_params", ";npdi")
   3.139 +</programlisting>
   3.140 +		</example>
   3.141 +	</section>
   3.142 +        <section>
   3.143 +                <title><varname>i_enum_suffix</varname> (string)</title>
   3.144 +                <para>
   3.145 +                The domain suffix to be used for i_enum_query() lookups.
   3.146 +                Can be overridden by a parameter to i_enum_query.
   3.147 +                </para>
   3.148 +                <para>
   3.149 +                Default value is <quote>e164.arpa.</quote>
   3.150 +                </para>
   3.151 +                <example>
   3.152 +                <title>Setting i_enum_suffix module parameter</title>
   3.153 +                <programlisting format="linespecific">
   3.154 +modparam("enum", "i_enum_suffix", "e1234.arpa.")
   3.155 +</programlisting>
   3.156 +                </example>
   3.157 +        </section>
   3.158 +        <section>
   3.159 +                <title><varname>branchlabel</varname> (string)</title>
   3.160 +                <para>
   3.161 +                This parameter determines which label i_enum_query() will use
   3.162 +                to branch off to the infrastructure ENUM tree.
   3.163 +                </para>
   3.164 +                <para>
   3.165 +                Default value is <quote>"i"</quote>
   3.166 +                </para>
   3.167 +                <example>
   3.168 +                <title>Setting brachlabel module parameter</title>
   3.169 +                <programlisting format="linespecific">
   3.170 +modparam("enum", "branchlabel", "i")
   3.171 +</programlisting>
   3.172 +                </example>
   3.173 +        </section>
   3.174 +        <section>
   3.175 +                <title><varname>bl_algorithm</varname> (string)</title>
   3.176 +                <para>
   3.177 +                This parameter determines which algorithm i_enum_query() will use
   3.178 +                to select the position in the DNS tree where the infrastructure tree
   3.179 +                branches off the user ENUM tree.
   3.180 +                </para>
   3.181 +                <para>
   3.182 +                If set to "cc", i_enum_query() will always inserts the
   3.183 +                label at the country-code level.
   3.184 +                Examples: i.1.e164.arpa, i.3.4.e164.arpa, i.2.5.3.e164.arpa
   3.185 +                </para>
   3.186 +                <para>
   3.187 +                If set to "txt", i_enum_query() will look for a TXT record at
   3.188 +                [branchlabel].[reverse-country-code].[i_enum_suffix] to indicate after how many digits the
   3.189 +                label should in inserted.
   3.190 +                <example>
   3.191 +                <title>Zone file example</title>
   3.192 +                <programlisting format="linespecific">
   3.193 +i.1.e164.arpa.                     IN TXT   "4"
   3.194 +9.9.9.8.7.6.5.i.4.3.2.1.e164.arpa. IN NAPTR "NAPTR content for  +1 234 5678 999"
   3.195 +</programlisting>
   3.196 +                </example>
   3.197 +                </para>
   3.198 +                <para>
   3.199 +                If set to "ebl", i_enum_query() will look for an EBL (ENUM Branch Label) record at
   3.200 +                [branchlabel].[reverse-country-code].[i_enum_suffix]. See http://www.ietf.org/internet-drafts/draft-lendl-enum-branch-location-record-00.txt for a description of that record and the
   3.201 +                meaning of the fields. The RR type for the EBL has not been allocated yet.
   3.202 +                This version of the code uses 65300. See resolve.h.
   3.203 +                <example>
   3.204 +                <title>Zone file example</title>
   3.205 +                <programlisting format="linespecific">
   3.206 +i.1.e164.arpa.     TYPE65300  \# 14 (
   3.207 +                              04    ; position
   3.208 +                              01 69 ; separator
   3.209 +                              04 65 31 36 34 04 61 72 70 61 00 ; e164.arpa
   3.210 +;                               )
   3.211 +9.9.9.8.7.6.5.i.4.3.2.1.e164.arpa. IN NAPTR "NAPTR content for  +1 234 5678 999"
   3.212 +</programlisting>
   3.213 +                </example>
   3.214 +                </para>
   3.215 +
   3.216 +                <para>
   3.217 +                Default value is <quote>cc</quote>
   3.218 +                </para>
   3.219 +                <example>
   3.220 +                <title>Setting the bl_algorithm module parameter</title>
   3.221 +                <programlisting format="linespecific">
   3.222 +modparam("enum", "bl_algorithm", "txt")
   3.223 +</programlisting>
   3.224 +                </example>
   3.225 +        </section>
   3.226 +
   3.227 +	</section>
   3.228 +
   3.229 +	<section>
   3.230 +	<title>Exported Functions</title>
   3.231 +	<section>
   3.232 +		<title>
   3.233 +		<function moreinfo="none">enum_query(["suffix"[,"service"]])</function>
   3.234 +		</title>
   3.235 +		<para>
   3.236 +		The function performs an enum query and rewrites the Request-URI with 
   3.237 +		the result of the query. See <xref linkend="sec-overview"/> for more 
   3.238 +		information.
   3.239 +		</para>
   3.240 +		<para>Meaning of the parameters is as follows:</para>
   3.241 +		<itemizedlist>
   3.242 +		<listitem>
   3.243 +			<para><emphasis>suffix</emphasis> - Suffix to be appended to the 
   3.244 +			domain name.
   3.245 +			</para>
   3.246 +		</listitem>
   3.247 +		<listitem>
   3.248 +			<para><emphasis>service</emphasis> - Service string to be used in 
   3.249 +			the service field.
   3.250 +			</para>
   3.251 +		</listitem>
   3.252 +		</itemizedlist>
   3.253 +		<para>
   3.254 +		This function can be used from REQUEST_ROUTE.
   3.255 +		</para>
   3.256 +		<example>
   3.257 +		<title><function moreinfo="none">enum_query</function> usage</title>
   3.258 +		<programlisting format="linespecific">
   3.259 +...
   3.260 +# search for "e2u+sip" in freenum.org 
   3.261 +enum_query("freenum.org.");
   3.262 +...
   3.263 +# search for "e2u+sip" in default tree (configured as parameter)
   3.264 +enum_query();
   3.265 +...
   3.266 +# search for "e2u+voice:sip" in e164.arpa
   3.267 +enum_query("e164.arpa.","voice");
   3.268 +...
   3.269 +# search for service type "sip" or "voice:sip" or "video:sip"
   3.270 +# note the '+' sign in front of the second parameter
   3.271 +enum_query("e164.arpa.","+sip+voice:sip+video:sip");
   3.272 +...
   3.273 +# quering for service sip and voice:sip
   3.274 +enum_query("e164.arpa.");
   3.275 +enum_query("e164.arpa.","voice");
   3.276 +# or use instead
   3.277 +enum_query("e164.arpa.","+sip+voice:sip");
   3.278 +...
   3.279 +</programlisting>
   3.280 +		</example>
   3.281 +	</section>
   3.282 +
   3.283 +	<section>
   3.284 +		<title>
   3.285 +		<function moreinfo="none">enum_pv_query("pvar"[,"suffix"[,"service"]])</function>
   3.286 +		</title>
   3.287 +		<para>
   3.288 +		The function performs an enum query on E.164 number stored
   3.289 +		in its pseudo variable argument and rewrites the Request-URI with 
   3.290 +		the result of the query. See <xref linkend="sec-overview"/> for more 
   3.291 +		information.
   3.292 +		</para>
   3.293 +		<para>Meaning of the parameters is as follows:</para>
   3.294 +		<itemizedlist>
   3.295 +		<listitem>
   3.296 +			<para><emphasis>pvar</emphasis> - Pseudo
   3.297 +		variable that holds an E.164 number on which enum
   3.298 +		query is performed.
   3.299 +			</para>
   3.300 +		</listitem>
   3.301 +		<listitem>
   3.302 +			<para><emphasis>suffix</emphasis> - Suffix to be appended to the 
   3.303 +			domain name.
   3.304 +			</para>
   3.305 +		</listitem>
   3.306 +		<listitem>
   3.307 +			<para><emphasis>service</emphasis> - Service string to be used in 
   3.308 +			the service field.
   3.309 +			</para>
   3.310 +		</listitem>
   3.311 +		</itemizedlist>
   3.312 +		<para>
   3.313 +		This function can be used from REQUEST_ROUTE.
   3.314 +		</para>
   3.315 +		<example>
   3.316 +		<title><function moreinfo="none">enum_pv_query</function> usage</title>
   3.317 +		<programlisting format="linespecific">
   3.318 +...
   3.319 +# search for "e2u+sip" in freenum.org 
   3.320 +enum_pv_query("$avp(i:100)", "freenum.org.");
   3.321 +...
   3.322 +# search for "e2u+sip" in default tree (configured as parameter)
   3.323 +enum_pv_query("$fU");
   3.324 +...
   3.325 +# search for "e2u+voice:sip" in e164.arpa
   3.326 +enum_pv_query("$avp(i:100)","e164.arpa.","voice");
   3.327 +...
   3.328 +# search for service type "sip" or "voice:sip" or "video:sip"
   3.329 +# note the '+' sign in front of the second parameter
   3.330 +enum_pv_query("$fU","e164.arpa.","+sip+voice:sip+video:sip");
   3.331 +...
   3.332 +# quering for service sip and voice:sip
   3.333 +enum_pv_query("$avp(i:100)","e164.arpa.");
   3.334 +enum_pv_query("$avp(i:100)","e164.arpa.","voice");
   3.335 +# or use instead
   3.336 +enum_pv_query("$avp(i:100)","e164.arpa.","+sip+voice:sip");
   3.337 +...
   3.338 +</programlisting>
   3.339 +		</example>
   3.340 +	</section>
   3.341 +
   3.342 +        <section>
   3.343 +                <title>
   3.344 +                <function moreinfo="none">i_enum_query(["suffix"[,"service"]])</function>
   3.345 +                </title>
   3.346 +                <para>
   3.347 +                The function performs an enum query and rewrites the Request-URI with
   3.348 +                the result of the query. This the Infrastructure-ENUM version of enum_query().
   3.349 +                The only difference to enum_query() is in the calculation of the
   3.350 +                FQDN where NAPTR records are looked for.
   3.351 +                </para>
   3.352 +                <para>
   3.353 +                See ftp://ftp.rfc-editor.org/in-notes/internet-drafts/draft-haberler-carrier-enum-01.txt
   3.354 +                for the rationale behind this function.
   3.355 +                </para>
   3.356 +        </section>
   3.357 +
   3.358 +	<section>
   3.359 +		<title><function moreinfo="none">is_from_user_enum()</function></title>
   3.360 +		<para>
   3.361 +		Checks if the user part of from <abbrev>URI</abbrev>
   3.362 +		is found in an enum lookup.
   3.363 +		Returns 1 if yes and -1 if not.
   3.364 +		</para>
   3.365 +		<para>
   3.366 +		This function can be used from REQUEST_ROUTE.
   3.367 +		</para>
   3.368 +		<example>
   3.369 +		<title><function moreinfo="none">is_from_user_enum</function> usage</title>
   3.370 +		<programlisting format="linespecific">
   3.371 +...
   3.372 +if (is_from_user_enum()) {
   3.373 +	....
   3.374 +};
   3.375 +...
   3.376 +</programlisting>
   3.377 +		</example>
   3.378 +	</section>
   3.379 +	</section>
   3.380 +</chapter>
   3.381 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/opensips/modules/enum/enum.c	Mon Jan 18 19:47:23 2010 +0100
     4.3 @@ -0,0 +1,1118 @@
     4.4 +/*
     4.5 + * $Id: enum.c 5901 2009-07-21 07:45:05Z bogdan_iancu $
     4.6 + *
     4.7 + * Enum and E164 related functions
     4.8 + *
     4.9 + * Copyright (C) 2002-2008 Juha Heinanen
    4.10 + *
    4.11 + * This file is part of opensips, a free SIP server.
    4.12 + *
    4.13 + * opensips is free software; you can redistribute it and/or modify
    4.14 + * it under the terms of the GNU General Public License as published by
    4.15 + * the Free Software Foundation; either version 2 of the License, or
    4.16 + * (at your option) any later version
    4.17 + *
    4.18 + * opensips is distributed in the hope that it will be useful,
    4.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.21 + * GNU General Public License for more details.
    4.22 + *
    4.23 + * You should have received a copy of the GNU General Public License 
    4.24 + * along with this program; if not, write to the Free Software 
    4.25 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    4.26 + *
    4.27 + */
    4.28 +
    4.29 +#include <stdlib.h>
    4.30 +
    4.31 +#include "enum.h"
    4.32 +#include "../../parser/parse_uri.h"
    4.33 +#include "../../parser/parse_from.h"
    4.34 +#include "../../ut.h"
    4.35 +#include "../../resolve.h"
    4.36 +#include "../../mem/mem.h"
    4.37 +#include "../../dset.h"
    4.38 +#include "../../qvalue.h"
    4.39 +#include "enum_mod.h"
    4.40 +#include "../../regexp.h"
    4.41 +#include "../../pvar.h"
    4.42 +
    4.43 +/*
    4.44 + * Input: E.164 number w/o leading +
    4.45 + *
    4.46 + * Output: number of digits in the country code
    4.47 + * 	   0 on invalid number
    4.48 + *
    4.49 + * convention:
    4.50 + *   3 digits is the default length of a country code.
    4.51 + *   country codes 1 and 7 are a single digit.
    4.52 + *   the following country codes are two digits: 20, 27, 30-34, 36, 39,
    4.53 + *     40, 41, 43-49, 51-58, 60-66, 81, 82, 84, 86, 90-95, 98.
    4.54 + */
    4.55 +static int cclen(const char *number)
    4.56 +{
    4.57 +	char d1,d2;
    4.58 +
    4.59 +	if (!number || (strlen(number) < 3))
    4.60 +		return(0);
    4.61 +
    4.62 +	d1 = number[0];
    4.63 +	d2 = number[1];
    4.64 +	
    4.65 +	if (!isdigit((int)d2)) 
    4.66 +		return(0);
    4.67 +
    4.68 +	switch(d1) {
    4.69 +		case '1':
    4.70 +		case '7':
    4.71 +			return(1);
    4.72 +		case '2':
    4.73 +			if ((d2 == '0') || (d1 == '7'))
    4.74 +				return(2);
    4.75 +			break;
    4.76 +		case '3':
    4.77 +			if ((d2 >= '0') && (d1 <= '4'))
    4.78 +				return(2);
    4.79 +			if ((d2 == '6') || (d1 == '9'))
    4.80 +				return(2);
    4.81 +			break;
    4.82 +		case '4':
    4.83 +			if (d2 != '2')
    4.84 +				return(2);
    4.85 +			break;
    4.86 +		case '5':
    4.87 +			if ((d2 >= '1') && (d1 <= '8'))
    4.88 +				return(2);
    4.89 +			break;
    4.90 +		case '6':
    4.91 +			if (d1 <= '6')
    4.92 +				return(2);
    4.93 +			break;
    4.94 +		case '8':
    4.95 +			if ((d2 == '1') || (d1 == '2') || (d1 == '4') || (d1 == '6')) 
    4.96 +				return(2);
    4.97 +			break;
    4.98 +		case '9':
    4.99 +			if (d1 <= '5')
   4.100 +				return(2);
   4.101 +			if (d2 == '8')
   4.102 +				return(2);
   4.103 +			break;
   4.104 +		default:
   4.105 +			return(0);
   4.106 +	}
   4.107 +
   4.108 +	return(3);
   4.109 +}
   4.110 +
   4.111 +
   4.112 +
   4.113 +/* return the length of the string until c, if not found returns n */
   4.114 +static inline int findchr(char* p, int c, unsigned int size)
   4.115 +{
   4.116 +	int len=0;
   4.117 +
   4.118 +	for(;len<size;p++){
   4.119 +		if (*p==(unsigned char)c) {
   4.120 +			return len;
   4.121 +		}
   4.122 +		len++;   
   4.123 +	}
   4.124 +	return len;
   4.125 +}
   4.126 +
   4.127 +
   4.128 +/* Parse NAPTR regexp field of the form !pattern!replacement! and return its
   4.129 + * components in pattern and replacement parameters.  Regexp field starts at
   4.130 + * address first and is len characters long.
   4.131 + */
   4.132 +static inline int parse_naptr_regexp(char* first, int len, str* pattern,
   4.133 +										str* replacement)
   4.134 +{
   4.135 +	char *second, *third;
   4.136 +
   4.137 +	if (len > 0) {
   4.138 +		if (*first == '!') {
   4.139 +			second = (char *)memchr((void *)(first + 1), '!', len - 1);
   4.140 +			if (second) {
   4.141 +				len = len - (second - first + 1);
   4.142 +				if (len > 0) {
   4.143 +					third = memchr(second + 1, '!', len);
   4.144 +					if (third) {
   4.145 +						pattern->len = second - first - 1;
   4.146 +						pattern->s = first + 1;
   4.147 +						replacement->len = third - second - 1;
   4.148 +						replacement->s = second + 1;
   4.149 +						return 1;
   4.150 +					} else {
   4.151 +						LM_ERR("Third ! missing from regexp\n");
   4.152 +						return -1;
   4.153 +					}
   4.154 +				} else {
   4.155 +					LM_ERR("Third ! missing from regexp\n");
   4.156 +					return -2;
   4.157 +				}
   4.158 +			} else {
   4.159 +				LM_ERR("Second ! missing from regexp\n");
   4.160 +				return -3;
   4.161 +			}
   4.162 +		} else {
   4.163 +			LM_ERR("First ! missing from regexp\n");
   4.164 +			return -4;
   4.165 +		}
   4.166 +	} else {
   4.167 +		LM_ERR("Regexp missing\n");
   4.168 +		return -5;
   4.169 +	}
   4.170 +}
   4.171 +/* Checks if NAPTR record has flag u and its services field
   4.172 + * e2u+[service:]sip or
   4.173 + * e2u+service[+service[+service[+...]]]
   4.174 + */
   4.175 +static inline int sip_match( struct naptr_rdata* naptr, str* service)
   4.176 +{
   4.177 +  if (service->len == 0) {
   4.178 +    return (naptr->flags_len == 1) &&
   4.179 +      ((naptr->flags[0] == 'u') || (naptr->flags[0] == 'U')) &&
   4.180 +      (naptr->services_len == 7) &&
   4.181 +      ((strncasecmp(naptr->services, "e2u+sip", 7) == 0) ||
   4.182 +       (strncasecmp(naptr->services, "sip+e2u", 7) == 0));
   4.183 +  } else if (service->s[0] != '+') {
   4.184 +    return (naptr->flags_len == 1) &&
   4.185 +      ((naptr->flags[0] == 'u') || (naptr->flags[0] == 'U')) &&
   4.186 +      (naptr->services_len == service->len + 8) &&
   4.187 +      (strncasecmp(naptr->services, "e2u+", 4) == 0) &&
   4.188 +      (strncasecmp(naptr->services + 4, service->s, service->len) == 0) &&
   4.189 +      (strncasecmp(naptr->services + 4 + service->len, ":sip", 4) == 0);
   4.190 +  } else { /* handle compound NAPTRs and multiple services */
   4.191 +    str bakservice, baknaptr; /* we bakup the str */
   4.192 +    int naptrlen, len;        /* length of the extracted service */
   4.193 +
   4.194 +    /* RFC 3761, NAPTR service field must start with E2U+ */
   4.195 +    if (strncasecmp(naptr->services, "e2u+", 4) != 0) {
   4.196 +      return 0;
   4.197 +    }
   4.198 +    baknaptr.s   = naptr->services + 4; /* leading 'e2u+' */
   4.199 +    baknaptr.len = naptr->services_len - 4;
   4.200 +    for (;;) { /* iterate over services in NAPTR */
   4.201 +      bakservice.s   = service->s + 1; /* leading '+' */
   4.202 +      bakservice.len = service->len - 1;
   4.203 +      naptrlen = findchr(baknaptr.s,'+',baknaptr.len);
   4.204 +
   4.205 +      for (;;) { /* iterate over services in enum_query */
   4.206 +        len = findchr(bakservice.s,'+',bakservice.len);
   4.207 +        if ((naptrlen == len ) && !strncasecmp(baknaptr.s, bakservice.s, len)){
   4.208 +          return 1;
   4.209 +        }
   4.210 +        if ( (bakservice.len -= len+1) > 0) {
   4.211 +          bakservice.s += len+1;
   4.212 +          continue;
   4.213 +        }
   4.214 +        break;
   4.215 +      }
   4.216 +      if ( (baknaptr.len -= naptrlen+1) > 0) {
   4.217 +        baknaptr.s += naptrlen+1;
   4.218 +        continue;
   4.219 +      }
   4.220 +      break;
   4.221 +    }
   4.222 +    /* no matching service found */
   4.223 +    return 0;
   4.224 +  }
   4.225 +}
   4.226 +
   4.227 +
   4.228 +/*
   4.229 + * Checks if argument is an e164 number starting with +
   4.230 + */
   4.231 +static inline int is_e164(str* _user)
   4.232 +{
   4.233 +	int i;
   4.234 +	char c;
   4.235 +	
   4.236 +	if ((_user->len > 2) && (_user->len < 17) && ((_user->s)[0] == '+')) {
   4.237 +		for (i = 1; i < _user->len; i++) {
   4.238 +			c = (_user->s)[i];
   4.239 +			if ((c < '0') || (c > '9')) return -1;
   4.240 +		}
   4.241 +		return 1;
   4.242 +	} else {
   4.243 +	    return -1;
   4.244 +	}
   4.245 +}
   4.246 +				
   4.247 +
   4.248 +/*
   4.249 + * Call is_from_user_enum_2 with module parameter suffix and default service.
   4.250 + */
   4.251 +int is_from_user_enum_0(struct sip_msg* _msg, char* _str1, char* _str2)
   4.252 +{
   4.253 +	return is_from_user_enum_2(_msg, (char *)(&suffix), (char *)(&service));
   4.254 +}
   4.255 +
   4.256 +/*
   4.257 + * Call is_from_user_enum_2 with given suffix and default service.
   4.258 + */
   4.259 +int is_from_user_enum_1(struct sip_msg* _msg, char* _suffix, char* _str2)
   4.260 +{
   4.261 +	return is_from_user_enum_2(_msg, _suffix, (char *)(&service));
   4.262 +}
   4.263 +
   4.264 +/*
   4.265 + * Check if from user is a valid enum based user, and check to make sure
   4.266 + * that the src_ip == an srv record that maps to the enum from user.
   4.267 + */
   4.268 +int is_from_user_enum_2(struct sip_msg* _msg, char* _suffix, char* _service)
   4.269 +{
   4.270 +	struct ip_addr addr;
   4.271 +	struct hostent* he;
   4.272 +	unsigned short zp;
   4.273 +	unsigned short proto;
   4.274 +	char *user_s;
   4.275 +	int user_len, i, j;
   4.276 +	char name[MAX_DOMAIN_SIZE];
   4.277 +	char uri[MAX_URI_SIZE];
   4.278 +	struct sip_uri *furi;
   4.279 +	struct sip_uri luri;
   4.280 +	struct rdata* head;
   4.281 +
   4.282 +	str* suffix;
   4.283 +	str* service;
   4.284 +
   4.285 +	struct rdata* l;
   4.286 +	struct naptr_rdata* naptr;
   4.287 +
   4.288 +	str pattern, replacement, result;
   4.289 +	char string[17];
   4.290 +
   4.291 +	if (parse_from_header(_msg) < 0) {
   4.292 +	    LM_ERR("Failed to parse From header\n");
   4.293 +	    return -1;
   4.294 +	}
   4.295 +	
   4.296 +	if(_msg->from==NULL || get_from(_msg)==NULL) {
   4.297 +	    LM_DBG("No From header\n");
   4.298 +	    return -1;
   4.299 +	}
   4.300 +
   4.301 +	if ((furi = parse_from_uri(_msg)) == NULL) {
   4.302 +	    LM_ERR("Failed to parse From URI\n");
   4.303 +	    return -1;
   4.304 +	}
   4.305 +
   4.306 +	suffix = (str*)_suffix;
   4.307 +	service = (str*)_service;
   4.308 +
   4.309 +	if (is_e164(&(furi->user)) == -1) {
   4.310 +	    LM_ERR("From URI user is not an E164 number\n");
   4.311 +	    return -1;
   4.312 +	}
   4.313 +
   4.314 +	/* assert: the from user is a valid formatted e164 string */
   4.315 +
   4.316 +	user_s = furi->user.s;
   4.317 +	user_len = furi->user.len;
   4.318 +
   4.319 +	j = 0;
   4.320 +	for (i = user_len - 1; i > 0; i--) {
   4.321 +		name[j] = user_s[i];
   4.322 +		name[j + 1] = '.';
   4.323 +		j = j + 2;
   4.324 +	}
   4.325 +
   4.326 +	memcpy(name + j, suffix->s, suffix->len + 1);
   4.327 +
   4.328 +	head = get_record(name, T_NAPTR);
   4.329 +
   4.330 +	if (head == 0) {
   4.331 +		LM_DBG("No NAPTR record found for %s.\n", name);
   4.332 +		return -3;
   4.333 +	}
   4.334 +
   4.335 +	/* we have the naptr records, loop and find an srv record with */
   4.336 +	/* same ip address as source ip address, if we do then true is returned */
   4.337 +
   4.338 +	for (l = head; l; l = l->next) {
   4.339 +
   4.340 +		if (l->type != T_NAPTR) continue; /*should never happen*/
   4.341 +		naptr = (struct naptr_rdata*)l->rdata;
   4.342 +		if (naptr == 0) {
   4.343 +			LM_ERR("Null rdata in DNS response\n");
   4.344 +			free_rdata_list(head);
   4.345 +			return -4;
   4.346 +		}
   4.347 +
   4.348 +		LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags "
   4.349 +		       "'%.*s', slen %u, services '%.*s', rlen %u, "
   4.350 +		       "regexp '%.*s'\n",
   4.351 +		       name, naptr->order, naptr->pref,
   4.352 +		    naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags), naptr->services_len,
   4.353 +		    (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
   4.354 +		    (int)(naptr->regexp_len), ZSW(naptr->regexp));
   4.355 +
   4.356 +		if (sip_match(naptr, service) != 0) {
   4.357 +			if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
   4.358 +					 &pattern, &replacement) < 0) {
   4.359 +				free_rdata_list(head); /*clean up*/
   4.360 +				LM_ERR("Parsing of NAPTR regexp failed\n");
   4.361 +				return -5;
   4.362 +			}
   4.363 +#ifdef LATER
   4.364 +			if ((pattern.len == 4) && (strncmp(pattern.s, "^.*$", 4) == 0)) {
   4.365 +				LM_DBG("Resulted in replacement: '%.*s'\n",
   4.366 +				       replacement.len, ZSW(replacement.s));				
   4.367 +				retval = set_uri(_msg, replacement.s, replacement.len);
   4.368 +				free_rdata_list(head); /*clean up*/
   4.369 +				return retval;
   4.370 +			}
   4.371 +#endif
   4.372 +			result.s = &(uri[0]);
   4.373 +			result.len = MAX_URI_SIZE;
   4.374 +			/* Avoid making copies of pattern and replacement */
   4.375 +			pattern.s[pattern.len] = (char)0;
   4.376 +			replacement.s[replacement.len] = (char)0;
   4.377 +			/* We have already checked the size of
   4.378 +			   _msg->parsed_uri.user.s */ 
   4.379 +			memcpy(&(string[0]), user_s, user_len);
   4.380 +			string[user_len] = (char)0;
   4.381 +			if (reg_replace(pattern.s, replacement.s, &(string[0]),
   4.382 +					&result) < 0) {
   4.383 +				pattern.s[pattern.len] = '!';
   4.384 +				replacement.s[replacement.len] = '!';
   4.385 +				LM_ERR("Regexp replace failed\n");
   4.386 +				free_rdata_list(head); /*clean up*/
   4.387 +				return -6;
   4.388 +			}
   4.389 +			LM_DBG("Resulted in replacement: '%.*s'\n",
   4.390 +			    result.len, ZSW(result.s));
   4.391 +
   4.392 +			if(parse_uri(result.s, result.len, &luri) < 0)
   4.393 +			{
   4.394 +				LM_ERR("Parsing of URI <%.*s> failed\n",
   4.395 +				       result.len, result.s);
   4.396 +				free_rdata_list(head); /*clean up*/
   4.397 +				return -7;
   4.398 +			}
   4.399 +
   4.400 +			pattern.s[pattern.len] = '!';
   4.401 +			replacement.s[replacement.len] = '!';
   4.402 +
   4.403 +			zp = 0;
   4.404 +			proto = PROTO_NONE;
   4.405 +			he = sip_resolvehost(&luri.host, &zp, &proto,
   4.406 +				(luri.type==SIPS_URI_T)?1:0 , 0);
   4.407 +
   4.408 +			hostent2ip_addr(&addr, he, 0);
   4.409 +
   4.410 +			if(ip_addr_cmp(&addr, &_msg->rcv.src_ip))
   4.411 +			{
   4.412 +				free_rdata_list(head);
   4.413 +				return(1);
   4.414 +			}
   4.415 +		}
   4.416 +	}
   4.417 +	free_rdata_list(head); /*clean up*/
   4.418 +	LM_DBG("FAIL\n");
   4.419 +
   4.420 +    /* must not have found the record */
   4.421 +    return(-8);
   4.422 +}
   4.423 +
   4.424 +
   4.425 +
   4.426 +/* 
   4.427 + * Add parameter to URI.
   4.428 + */
   4.429 +int add_uri_param(str *uri, str *param, str *new_uri)
   4.430 +{
   4.431 +	struct sip_uri puri;
   4.432 +	char *at;
   4.433 +
   4.434 +	if (parse_uri(uri->s, uri->len, &puri) < 0) {
   4.435 +		return 0;
   4.436 +	}
   4.437 +
   4.438 +	/* if current uri has no headers, pad param to the end of uri */
   4.439 +	if (puri.headers.len == 0) {
   4.440 +		memcpy(uri->s + uri->len, param->s, param->len);
   4.441 +		uri->len = uri->len + param->len;
   4.442 +		new_uri->len = 0;
   4.443 +		return 1;
   4.444 +	}
   4.445 +
   4.446 +	/* otherwise take the long path and create new_uri */
   4.447 +	at = new_uri->s;
   4.448 +	switch (puri.type) {
   4.449 +	case SIP_URI_T:
   4.450 +	    memcpy(at, "sip:", 4);
   4.451 +	    at = at + 4;
   4.452 +	    break;
   4.453 +	case SIPS_URI_T:
   4.454 +	    memcpy(at, "sips:", 5);
   4.455 +	    at = at + 5;
   4.456 +	    break;
   4.457 +	case TEL_URI_T:
   4.458 +	    memcpy(at, "tel:", 4);
   4.459 +	    at = at + 4;
   4.460 +	    break;
   4.461 +	case TELS_URI_T:
   4.462 +	    memcpy(at, "tels:", 5);
   4.463 +	    at = at + 5;
   4.464 +	    break;
   4.465 +	default:
   4.466 +	    LM_ERR("Unknown URI scheme <%d>\n", puri.type);
   4.467 +	    return 0;
   4.468 +	}
   4.469 +	if (puri.user.len) {
   4.470 +		memcpy(at, puri.user.s, puri.user.len);
   4.471 +		at = at + puri.user.len;
   4.472 +		if (puri.passwd.len) {
   4.473 +			*at = ':';
   4.474 +			at = at + 1;
   4.475 +			memcpy(at, puri.passwd.s, puri.passwd.len);
   4.476 +			at = at + puri.passwd.len;
   4.477 +		};
   4.478 +		*at = '@';
   4.479 +		at = at + 1;
   4.480 +	}
   4.481 +	memcpy(at, puri.host.s, puri.host.len);
   4.482 +	at = at + puri.host.len;
   4.483 +	if (puri.port.len) {
   4.484 +		*at = ':';
   4.485 +		at = at + 1;
   4.486 +		memcpy(at, puri.port.s, puri.port.len);
   4.487 +		at = at + puri.port.len;
   4.488 +	}
   4.489 +	if (puri.params.len) {
   4.490 +		*at = ';';
   4.491 +		at = at + 1;
   4.492 +		memcpy(at, puri.params.s, puri.params.len);
   4.493 +		at = at + puri.params.len;
   4.494 +	}
   4.495 +	memcpy(at, param->s, param->len);
   4.496 +	at = at + param->len;
   4.497 +	*at = '?';
   4.498 +	at = at + 1;
   4.499 +	memcpy(at, puri.headers.s, puri.headers.len);
   4.500 +	at = at + puri.headers.len;
   4.501 +	new_uri->len = at - new_uri->s;
   4.502 +	return 1;
   4.503 +}
   4.504 +
   4.505 +/*
   4.506 + * Tests if one result record is "greater" that the other.  Non-NAPTR records
   4.507 + * greater that NAPTR record.  An invalid NAPTR record is greater than a 
   4.508 + * valid one.  Valid NAPTR records are compared based on their
   4.509 + * (order,preference).
   4.510 + */
   4.511 +static inline int naptr_greater(struct rdata* a, struct rdata* b)
   4.512 +{
   4.513 +	struct naptr_rdata *na, *nb;
   4.514 +
   4.515 +	if (a->type != T_NAPTR) return 1;
   4.516 +	if (b->type != T_NAPTR) return 0;
   4.517 +
   4.518 +	na = (struct naptr_rdata*)a->rdata;
   4.519 +	if (na == 0) return 1;
   4.520 +
   4.521 +	nb = (struct naptr_rdata*)b->rdata;
   4.522 +	if (nb == 0) return 0;
   4.523 +	
   4.524 +	return (((na->order) << 16) + na->pref) >
   4.525 +		(((nb->order) << 16) + nb->pref);
   4.526 +}
   4.527 +	
   4.528 +	
   4.529 +/*
   4.530 + * Bubble sorts result record list according to naptr (order,preference).
   4.531 + */
   4.532 +static inline void naptr_sort(struct rdata** head)
   4.533 +{
   4.534 +	struct rdata *p, *q, *r, *s, *temp, *start;
   4.535 +
   4.536 +        /* r precedes p and s points to the node up to which comparisons
   4.537 +         are to be made */ 
   4.538 +
   4.539 +	s = NULL;
   4.540 +	start = *head;
   4.541 +	while ( s != start -> next ) { 
   4.542 +		r = p = start ; 
   4.543 +		q = p -> next ;
   4.544 +		while ( p != s ) { 
   4.545 +			if ( naptr_greater(p, q) ) { 
   4.546 +				if ( p == start ) { 
   4.547 +					temp = q -> next ; 
   4.548 +					q -> next = p ; 
   4.549 +					p -> next = temp ;
   4.550 +					start = q ; 
   4.551 +					r = q ; 
   4.552 +				} else {
   4.553 +					temp = q -> next ; 
   4.554 +					q -> next = p ; 
   4.555 +					p -> next = temp ;
   4.556 +					r -> next = q ; 
   4.557 +					r = q ; 
   4.558 +				} 
   4.559 +			} else {
   4.560 +				r = p ; 
   4.561 +				p = p -> next ; 
   4.562 +			} 
   4.563 +			q = p -> next ; 
   4.564 +			if ( q == s ) s = p ; 
   4.565 +		}
   4.566 +	}
   4.567 +	*head = start;
   4.568 +}	
   4.569 +	
   4.570 +
   4.571 +/*
   4.572 + * Makes enum query on name.  On success, rewrites user part and 
   4.573 + * replaces Request-URI.
   4.574 + */
   4.575 +int do_query(struct sip_msg* _msg, char *user, char *name, str *service) {
   4.576 +
   4.577 +    char uri[MAX_URI_SIZE];
   4.578 +    char new_uri[MAX_URI_SIZE];
   4.579 +    unsigned int priority, curr_prio, first;
   4.580 +    qvalue_t q;
   4.581 +    struct rdata* head;
   4.582 +    struct rdata* l;
   4.583 +    struct naptr_rdata* naptr;
   4.584 +    str pattern, replacement, result, new_result;
   4.585 +
   4.586 +    head = get_record(name, T_NAPTR);
   4.587 +    
   4.588 +    if (head == 0) {
   4.589 +	LM_DBG("No NAPTR record found for %s.\n", name);
   4.590 +	return -1;
   4.591 +    }
   4.592 +    
   4.593 +    naptr_sort(&head);
   4.594 +
   4.595 +    q = MAX_Q - 10;
   4.596 +    curr_prio = 0;
   4.597 +    first = 1;
   4.598 +
   4.599 +    for (l = head; l; l = l->next) {
   4.600 +
   4.601 +	if (l->type != T_NAPTR) continue; /*should never happen*/
   4.602 +	naptr = (struct naptr_rdata*)l->rdata;
   4.603 +	if (naptr == 0) {
   4.604 +	    LM_ERR("Null rdata in DNS response\n");
   4.605 +	    continue;
   4.606 +	}
   4.607 +
   4.608 +	LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags '%.*s', "
   4.609 +	       "slen %u, services '%.*s', rlen %u, regexp '%.*s'\n",
   4.610 +	       name, naptr->order, naptr->pref,
   4.611 +	    naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
   4.612 +	    naptr->services_len,
   4.613 +	    (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
   4.614 +	    (int)(naptr->regexp_len), ZSW(naptr->regexp));
   4.615 +	
   4.616 +	if (sip_match(naptr, service) == 0) continue;
   4.617 +	
   4.618 +	if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
   4.619 +			       &pattern, &replacement) < 0) {
   4.620 +	    LM_ERR("Parsing of NAPTR regexp failed\n");
   4.621 +	    continue;
   4.622 +	}
   4.623 +	result.s = &(uri[0]);
   4.624 +	result.len = MAX_URI_SIZE;
   4.625 +	/* Avoid making copies of pattern and replacement */
   4.626 +	pattern.s[pattern.len] = (char)0;
   4.627 +	replacement.s[replacement.len] = (char)0;
   4.628 +	if (reg_replace(pattern.s, replacement.s, user, &result) < 0) {
   4.629 +	    pattern.s[pattern.len] = '!';
   4.630 +	    replacement.s[replacement.len] = '!';
   4.631 +	    LM_ERR("Regexp replace failed\n");
   4.632 +	    continue;
   4.633 +	}
   4.634 +	LM_DBG("Resulted in replacement: '%.*s'\n", result.len, ZSW(result.s));
   4.635 +	pattern.s[pattern.len] = '!';
   4.636 +	replacement.s[replacement.len] = '!';
   4.637 +	
   4.638 +	if (param.len > 0) {
   4.639 +	    if (result.len + param.len > MAX_URI_SIZE - 1) {
   4.640 +		LM_ERR("URI is too long\n");
   4.641 +		continue;
   4.642 +	    }
   4.643 +	    new_result.s = &(new_uri[0]);
   4.644 +	    new_result.len = MAX_URI_SIZE;
   4.645 +	    if (add_uri_param(&result, &param, &new_result) == 0) {
   4.646 +		LM_ERR("Parsing of URI <%.*s> failed\n",
   4.647 +		       result.len, result.s);
   4.648 +		continue;
   4.649 +	    }
   4.650 +	    if (new_result.len > 0) {
   4.651 +		result = new_result;
   4.652 +	    }
   4.653 +	}
   4.654 +	
   4.655 +	if (first) {
   4.656 +	    if (set_ruri(_msg, &result) == -1) {
   4.657 +		goto done;
   4.658 +	    }
   4.659 +	    set_ruri_q(q);
   4.660 +	    first = 0;
   4.661 +	    curr_prio = ((naptr->order) << 16) + naptr->pref;
   4.662 +	} else {
   4.663 +	    priority = ((naptr->order) << 16) + naptr->pref;
   4.664 +	    if (priority > curr_prio) {
   4.665 +		q = q - 10;
   4.666 +		curr_prio = priority;
   4.667 +	    }
   4.668 +	    if (append_branch(_msg, &result, 0, 0, q, 0, 0) == -1) {
   4.669 +		goto done;
   4.670 +	    }
   4.671 +	}
   4.672 +    }
   4.673 +
   4.674 +done:
   4.675 +    free_rdata_list(head);
   4.676 +    return first ? -1 : 1;
   4.677 +}
   4.678 +
   4.679 +	
   4.680 +/*
   4.681 + * Call enum_query_2 with module parameter suffix and default service.
   4.682 + */
   4.683 +int enum_query_0(struct sip_msg* _msg, char* _str1, char* _str2)
   4.684 +{
   4.685 +	return enum_query_2(_msg, (char *)(&suffix), (char *)(&service));
   4.686 +}
   4.687 +
   4.688 +
   4.689 +/*
   4.690 + * Call enum_query_2 with given suffix and default service.
   4.691 + */
   4.692 +int enum_query_1(struct sip_msg* _msg, char* _suffix, char* _str2)
   4.693 +{
   4.694 +	return enum_query_2(_msg, _suffix, (char *)(&service));
   4.695 +}
   4.696 +
   4.697 +
   4.698 +/*
   4.699 + * See documentation in README file.
   4.700 + */
   4.701 +int enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service)
   4.702 +{
   4.703 +	char *user_s;
   4.704 +	int user_len, i, j;
   4.705 +	char name[MAX_DOMAIN_SIZE];
   4.706 +	char string[17];
   4.707 +
   4.708 +	str *suffix, *service;
   4.709 +
   4.710 +	suffix = (str*)_suffix;
   4.711 +	service = (str*)_service;
   4.712 +
   4.713 +	if (parse_sip_msg_uri(_msg) < 0) {
   4.714 +		LM_ERR("Parsing of R-URI failed\n");
   4.715 +		return -1;
   4.716 +	}
   4.717 +
   4.718 +	if (is_e164(&(_msg->parsed_uri.user)) == -1) {
   4.719 +		LM_ERR("R-URI user is not an E164 number\n");
   4.720 +		return -1;
   4.721 +	}
   4.722 +
   4.723 +	user_s = _msg->parsed_uri.user.s;
   4.724 +	user_len = _msg->parsed_uri.user.len;
   4.725 +
   4.726 +	memcpy(&(string[0]), user_s, user_len);
   4.727 +	string[user_len] = (char)0;
   4.728 +
   4.729 +	j = 0;
   4.730 +	for (i = user_len - 1; i > 0; i--) {
   4.731 +		name[j] = user_s[i];
   4.732 +		name[j + 1] = '.';
   4.733 +		j = j + 2;
   4.734 +	}
   4.735 +
   4.736 +	memcpy(name + j, suffix->s, suffix->len + 1);
   4.737 +
   4.738 +	return do_query(_msg, string, name, service);
   4.739 +}
   4.740 +
   4.741 +
   4.742 +/*********** INFRASTRUCTURE ENUM ***************/
   4.743 +
   4.744 +/*
   4.745 + * Call enum_query_2 with default suffix and service.
   4.746 + */
   4.747 +int i_enum_query_0(struct sip_msg* _msg, char* _suffix, char* _service)
   4.748 +{
   4.749 +	return i_enum_query_2(_msg, (char *)(&i_suffix), (char *)(&service));
   4.750 +}
   4.751 +
   4.752 +/*
   4.753 + * Call enum_query_2 with given suffix and default service.
   4.754 + */
   4.755 +int i_enum_query_1(struct sip_msg* _msg, char* _suffix, char* _service)
   4.756 +{
   4.757 +	return i_enum_query_2(_msg, _suffix, (char *)(&service));
   4.758 +}
   4.759 +
   4.760 +
   4.761 +int i_enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service)
   4.762 +{
   4.763 +	char *user_s;
   4.764 +	int user_len, i, j;
   4.765 +	char name[MAX_DOMAIN_SIZE];
   4.766 +	char apex[MAX_COMPONENT_SIZE + 1];
   4.767 +	char separator[MAX_COMPONENT_SIZE + 1];
   4.768 +	int sdl = 0;    /* subdomain location: infrastructure enum offset */
   4.769 +	int cc_len;
   4.770 +	struct rdata* head;
   4.771 +
   4.772 +	char string[17];
   4.773 +
   4.774 +	str *suffix, *service;
   4.775 +
   4.776 +	suffix = (str*)_suffix;
   4.777 +	service = (str*)_service;
   4.778 +
   4.779 +	if (parse_sip_msg_uri(_msg) < 0) {
   4.780 +		LM_ERR("Parsing of R-URI failed\n");
   4.781 +		return -1;
   4.782 +	}
   4.783 +
   4.784 +	if (is_e164(&(_msg->parsed_uri.user)) == -1) {
   4.785 +		LM_ERR("R-URI user is not an E164 number\n");
   4.786 +		return -1;
   4.787 +	}
   4.788 +
   4.789 +	user_s = _msg->parsed_uri.user.s;
   4.790 +	user_len = _msg->parsed_uri.user.len;
   4.791 +
   4.792 +	/* make sure we don't run out of space in strings */
   4.793 +	if (( 2*user_len + MAX_COMPONENT_SIZE + MAX_COMPONENT_SIZE + 4) > MAX_DOMAIN_SIZE) {
   4.794 +		LM_ERR("Strings too long\n");
   4.795 +		return -1;
   4.796 +	}
   4.797 +	if ( i_branchlabel.len > MAX_COMPONENT_SIZE ) {
   4.798 +		LM_ERR("i_branchlabel too long\n");
   4.799 +		return -1;
   4.800 +	}
   4.801 +	if ( suffix->len > MAX_COMPONENT_SIZE ) {
   4.802 +		LM_ERR("Suffix too long\n");
   4.803 +		return -1;
   4.804 +	}
   4.805 +
   4.806 +
   4.807 +	memcpy(&(string[0]), user_s, user_len);
   4.808 +	string[user_len] = (char)0;
   4.809 +
   4.810 +	/* Set up parameters as for user-enum */
   4.811 +	memcpy(apex,  suffix->s , suffix->len);
   4.812 +	apex[suffix->len] = (char)0;
   4.813 +	sdl = 0;		/* where to insert i-enum separator */
   4.814 +	separator[0] = 0;	/* don't insert anything */
   4.815 +
   4.816 +	cc_len = cclen(string + 1);
   4.817 +
   4.818 +	if (!strncasecmp(i_bl_alg.s,"ebl",i_bl_alg.len)) {
   4.819 +		sdl = cc_len; /* default */
   4.820 +
   4.821 +		j = 0;
   4.822 +		memcpy(name, i_branchlabel.s, i_branchlabel.len);
   4.823 +		j += i_branchlabel.len;
   4.824 +		name[j++] = '.';
   4.825 +
   4.826 +		for (i = cc_len ; i > 0; i--) {
   4.827 +			name[j++] = user_s[i];
   4.828 +			name[j++] = '.';
   4.829 +		}
   4.830 +		memcpy(name + j, suffix->s, suffix->len + 1);
   4.831 +
   4.832 +		LM_DBG("Looking for EBL record for %s.\n", name); 
   4.833 +		head = get_record(name, T_EBL);
   4.834 +		if (head == 0) {
   4.835 +			LM_DBG("No EBL found for %s. Defaulting to user ENUM.\n",name);
   4.836 +		} else {
   4.837 +		    	struct ebl_rdata* ebl;
   4.838 +			ebl = (struct ebl_rdata *) head->rdata;
   4.839 +
   4.840 +			LM_DBG("EBL record for %s is %d / %.*s / %.*s.\n",
   4.841 +			       name, ebl->position, (int)ebl->separator_len,
   4.842 +			       ebl->separator,(int)ebl->apex_len, ebl->apex);
   4.843 +
   4.844 +			if ((ebl->apex_len > MAX_COMPONENT_SIZE) || (ebl->separator_len > MAX_COMPONENT_SIZE)) {
   4.845 +				LM_ERR("EBL strings too long\n"); 
   4.846 +				return -1;
   4.847 +			}
   4.848 +
   4.849 +			if (ebl->position > 15)  {
   4.850 +				LM_ERR("EBL position too large (%d)\n",
   4.851 +				       ebl->position); 
   4.852 +				return -1;
   4.853 +			}
   4.854 +
   4.855 +			sdl = ebl->position;
   4.856 +
   4.857 +			memcpy(separator, ebl->separator, ebl->separator_len);
   4.858 +			separator[ebl->separator_len] = 0;
   4.859 +
   4.860 +			memcpy(apex, ebl->apex, ebl->apex_len);
   4.861 +			apex[ebl->apex_len] = 0;
   4.862 +			free_rdata_list(head);
   4.863 +		}
   4.864 +	} else if (!strncasecmp(i_bl_alg.s,"txt",i_bl_alg.len)) {
   4.865 +		sdl = cc_len; /* default */
   4.866 +		memcpy(separator, i_branchlabel.s, i_branchlabel.len);
   4.867 +		separator[i_branchlabel.len] = 0;
   4.868 +		/* no change to apex */
   4.869 +
   4.870 +		j = 0;
   4.871 +		memcpy(name, i_branchlabel.s, i_branchlabel.len);
   4.872 +		j += i_branchlabel.len;
   4.873 +		name[j++] = '.';
   4.874 +
   4.875 +		for (i = cc_len ; i > 0; i--) {
   4.876 +			name[j++] = user_s[i];
   4.877 +			name[j++] = '.';
   4.878 +		}
   4.879 +		memcpy(name + j, suffix->s, suffix->len + 1);
   4.880 +
   4.881 +		head = get_record(name, T_TXT);
   4.882 +		if (head == 0) {
   4.883 +			LM_DBG("TXT found for %s. Defaulting to %d\n",
   4.884 +			       name, cc_len);
   4.885 +		} else {
   4.886 +			sdl = atoi(((struct txt_rdata*)head->rdata)->txt);
   4.887 +			LM_DBG("TXT record for %s is %d.\n", name, sdl);
   4.888 +
   4.889 +			if ((sdl < 0) || (sdl > 10)) {
   4.890 +				LM_ERR("Sdl %d out of bounds. Set back to cc_len.\n", sdl);
   4.891 +				sdl = cc_len;
   4.892 +			}
   4.893 +			free_rdata_list(head);
   4.894 +		}
   4.895 +	} else {	/* defaults to CC */
   4.896 +		sdl = cc_len;
   4.897 +		memcpy(separator, i_branchlabel.s, i_branchlabel.len);
   4.898 +		separator[i_branchlabel.len] = 0;
   4.899 +		/* no change to apex */
   4.900 +	}
   4.901 +
   4.902 +	j = 0;
   4.903 +	sdl++; /* to avoid comparing i to (sdl+1) */
   4.904 +	for (i = user_len - 1; i > 0; i--) {
   4.905 +		name[j] = user_s[i];
   4.906 +		name[j + 1] = '.';
   4.907 +		j = j + 2;
   4.908 +		if (separator[0] && (i == sdl)) { /* insert the I-ENUM separator here? */
   4.909 +			strcpy(name + j, separator);  /* we've checked string sizes. */
   4.910 +			j += strlen(separator);
   4.911 +			name[j++] = '.';
   4.912 +		}
   4.913 +	}
   4.914 +
   4.915 +	memcpy(name + j, apex, strlen(apex)+1);
   4.916 +
   4.917 +	return do_query(_msg, string, name, service);
   4.918 +}
   4.919 +
   4.920 +
   4.921 +
   4.922 +/******************* FQUERY *******************/
   4.923 +
   4.924 +
   4.925 +/*
   4.926 + * Call enum_pv_query_3 with pv arg, module parameter suffix,
   4.927 + * and default service.
   4.928 + */
   4.929 +int enum_pv_query_1(struct sip_msg* _msg, char* _sp)
   4.930 +{
   4.931 +    return enum_pv_query_3(_msg, _sp, (char *)(&suffix), (char *)(&service));
   4.932 +}
   4.933 +
   4.934 +/*
   4.935 + * Call enum_pv_query_3 with pv and suffix args and default service.
   4.936 + */
   4.937 +int enum_pv_query_2(struct sip_msg* _msg, char* _sp, char* _suffix)
   4.938 +{
   4.939 +    return enum_pv_query_3(_msg, _sp, _suffix, (char *)(&service));
   4.940 +}
   4.941 +
   4.942 +/*
   4.943 + * See documentation in README file.
   4.944 + */
   4.945 +
   4.946 +int enum_pv_query_3(struct sip_msg* _msg, char* _sp, char* _suffix,
   4.947 +		    char* _service)
   4.948 +{
   4.949 +	char *user_s;
   4.950 +	int user_len, i, j, first;
   4.951 +	char name[MAX_DOMAIN_SIZE];
   4.952 +	char uri[MAX_URI_SIZE];
   4.953 +	char new_uri[MAX_URI_SIZE];
   4.954 +	unsigned int priority, curr_prio;
   4.955 +	qvalue_t q;
   4.956 +	char tostring[17];
   4.957 +	struct rdata* head;
   4.958 +	struct rdata* l;
   4.959 +	struct naptr_rdata* naptr;
   4.960 +	str pattern, replacement, result, new_result;
   4.961 +	str *suffix, *service;
   4.962 +	char string[17];
   4.963 +	pv_spec_t *sp;
   4.964 +	pv_value_t pv_val;
   4.965 +
   4.966 +	sp = (pv_spec_t *)_sp;
   4.967 +	suffix = (str*)_suffix;
   4.968 +	service = (str*)_service;
   4.969 +
   4.970 +	/*
   4.971 +	 *  Get R-URI user to tostring
   4.972 +	 */
   4.973 +	if (parse_sip_msg_uri(_msg) < 0) {
   4.974 +		LM_ERR("R-URI parsing failed\n");
   4.975 +		return -1;
   4.976 +	}
   4.977 +
   4.978 +	if (is_e164(&(_msg->parsed_uri.user)) == -1) {
   4.979 +		LM_ERR("R-URI user is not an E164 number\n");
   4.980 +		return -1;
   4.981 +	}
   4.982 +
   4.983 +	user_s = _msg->parsed_uri.user.s;
   4.984 +	user_len = _msg->parsed_uri.user.len;
   4.985 +
   4.986 +	memcpy(&(tostring[0]), user_s, user_len);
   4.987 +	tostring[user_len] = (char)0;
   4.988 +
   4.989 +	/*
   4.990 +	 * Get E.164 number from pseudo variable
   4.991 +         */
   4.992 +	if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
   4.993 +	    if (pv_val.flags & PV_VAL_STR) {
   4.994 +		if (pv_val.rs.len == 0 || pv_val.rs.s == NULL) {
   4.995 +		    LM_DBG("Missing E.164 number\n");
   4.996 +		    return -1;
   4.997 +		}
   4.998 +	    } else {
   4.999 +		LM_DBG("Pseudo variable value is not string\n");
  4.1000 +		return -1;
  4.1001 +	}
  4.1002 +	} else {
  4.1003 +	    LM_DBG("Cannot get pseudo variable value\n");
  4.1004 +	    return -1;
  4.1005 +	}
  4.1006 +	if (is_e164(&(pv_val.rs)) == -1) {
  4.1007 +	    LM_ERR("pseudo variable does not contain an E164 number\n");
  4.1008 +	    return -1;
  4.1009 +	}
  4.1010 +
  4.1011 +	user_s = pv_val.rs.s;
  4.1012 +	user_len = pv_val.rs.len;
  4.1013 +
  4.1014 +	memcpy(&(string[0]), user_s, user_len);
  4.1015 +	string[user_len] = (char)0;
  4.1016 +
  4.1017 +	j = 0;
  4.1018 +	for (i = user_len - 1; i > 0; i--) {
  4.1019 +		name[j] = user_s[i];
  4.1020 +		name[j + 1] = '.';
  4.1021 +		j = j + 2;
  4.1022 +	}
  4.1023 +
  4.1024 +	memcpy(name + j, suffix->s, suffix->len + 1);
  4.1025 +
  4.1026 +	head = get_record(name, T_NAPTR);
  4.1027 +
  4.1028 +	if (head == 0) {
  4.1029 +		LM_DBG("No NAPTR record found for %s.\n", name);
  4.1030 +		return -1;
  4.1031 +	}
  4.1032 +
  4.1033 +	naptr_sort(&head);
  4.1034 +
  4.1035 +	q = MAX_Q - 10;
  4.1036 +	curr_prio = 0;
  4.1037 +	first = 1;
  4.1038 +
  4.1039 +	for (l = head; l; l = l->next) {
  4.1040 +
  4.1041 +		if (l->type != T_NAPTR) continue; /*should never happen*/
  4.1042 +		naptr = (struct naptr_rdata*)l->rdata;
  4.1043 +		if (naptr == 0) {
  4.1044 +			LM_ERR("Null rdata in DNS response\n");
  4.1045 +			continue;
  4.1046 +		}
  4.1047 +
  4.1048 +		LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags "
  4.1049 +		       "'%.*s', slen %u, services '%.*s', rlen %u, "
  4.1050 +		       "regexp '%.*s'\n",
  4.1051 +		       name, naptr->order, naptr->pref,
  4.1052 +		    naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
  4.1053 +		    naptr->services_len,
  4.1054 +		    (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
  4.1055 +		    (int)(naptr->regexp_len), ZSW(naptr->regexp));
  4.1056 +
  4.1057 +		if (sip_match(naptr, service) == 0) continue;
  4.1058 +
  4.1059 +		if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
  4.1060 +				       &pattern, &replacement) < 0) {
  4.1061 +			LM_ERR("Parsing of NAPTR regexp failed\n");
  4.1062 +			continue;
  4.1063 +		}
  4.1064 +		result.s = &(uri[0]);
  4.1065 +		result.len = MAX_URI_SIZE;
  4.1066 +		/* Avoid making copies of pattern and replacement */
  4.1067 +		pattern.s[pattern.len] = (char)0;
  4.1068 +		replacement.s[replacement.len] = (char)0;
  4.1069 +		if (reg_replace(pattern.s, replacement.s, &(tostring[0]),
  4.1070 +				&result) < 0) {
  4.1071 +			pattern.s[pattern.len] = '!';
  4.1072 +			replacement.s[replacement.len] = '!';
  4.1073 +			LM_ERR("Regexp replace failed\n");
  4.1074 +			continue;
  4.1075 +		}
  4.1076 +		LM_DBG("Resulted in replacement: '%.*s'\n",
  4.1077 +		       result.len, ZSW(result.s));
  4.1078 +		pattern.s[pattern.len] = '!';
  4.1079 +		replacement.s[replacement.len] = '!';
  4.1080 +		
  4.1081 +		if (param.len > 0) {
  4.1082 +			if (result.len + param.len > MAX_URI_SIZE - 1) {
  4.1083 +				LM_ERR("URI is too long\n");
  4.1084 +				continue;
  4.1085 +			}
  4.1086 +			new_result.s = &(new_uri[0]);
  4.1087 +			new_result.len = MAX_URI_SIZE;
  4.1088 +			if (add_uri_param(&result, &param, &new_result) == 0) {
  4.1089 +				LM_ERR("Parsing of URI <%.*s> failed\n",
  4.1090 +				       result.len, result.s);
  4.1091 +				continue;
  4.1092 +			}
  4.1093 +			if (new_result.len > 0) {
  4.1094 +				result = new_result;
  4.1095 +			}
  4.1096 +		}
  4.1097 +
  4.1098 +		if (first) {
  4.1099 +			if (set_ruri(_msg, &result) == -1) {
  4.1100 +				goto done;
  4.1101 +			}
  4.1102 +			set_ruri_q(q);
  4.1103 +			first = 0;
  4.1104 +			curr_prio = ((naptr->order) << 16) + naptr->pref;
  4.1105 +		} else {
  4.1106 +			priority = ((naptr->order) << 16) + naptr->pref;
  4.1107 +			if (priority > curr_prio) {
  4.1108 +				q = q - 10;
  4.1109 +				curr_prio = priority;
  4.1110 +			}
  4.1111 +			if (append_branch(_msg, &result, 0, 0, q, 0, 0) == -1) {
  4.1112 +				goto done;
  4.1113 +			}
  4.1114 +		}
  4.1115 +	}
  4.1116 +
  4.1117 +done:
  4.1118 +	free_rdata_list(head);
  4.1119 +	return first ? -1 : 1;
  4.1120 +}
  4.1121 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/opensips/modules/enum/enum.h	Mon Jan 18 19:47:23 2010 +0100
     5.3 @@ -0,0 +1,70 @@
     5.4 +/*
     5.5 + * $Id: enum.h 5901 2009-07-21 07:45:05Z bogdan_iancu $
     5.6 + *
     5.7 + * Header file for Enum and E164 related functions
     5.8 + *
     5.9 + * Copyright (C) 2002-2008 Juha Heinanen
    5.10 + *
    5.11 + * This file is part of opensips, a free SIP server.
    5.12 + *
    5.13 + * opensips is free software; you can redistribute it and/or modify
    5.14 + * it under the terms of the GNU General Public License as published by
    5.15 + * the Free Software Foundation; either version 2 of the License, or
    5.16 + * (at your option) any later version
    5.17 + *
    5.18 + * opensips is distributed in the hope that it will be useful,
    5.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.21 + * GNU General Public License for more details.
    5.22 + *
    5.23 + * You should have received a copy of the GNU General Public License 
    5.24 + * along with this program; if not, write to the Free Software 
    5.25 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.26 + */
    5.27 +
    5.28 +
    5.29 +#ifndef ENUM_H
    5.30 +#define ENUM_H
    5.31 +
    5.32 +
    5.33 +#include "../../parser/msg_parser.h"
    5.34 +
    5.35 +
    5.36 +#define MAX_DOMAIN_SIZE 256
    5.37 +#define MAX_COMPONENT_SIZE 32  /* separator, apex, ... This simplifies checks */
    5.38 +		
    5.39 +
    5.40 +/*
    5.41 + * Check if from user is an e164 number and has a naptr record
    5.42 + */
    5.43 +int is_from_user_enum_0(struct sip_msg* _msg, char* _str1, char* _str2);
    5.44 +int is_from_user_enum_1(struct sip_msg* _msg, char* _suffix, char* _str2);
    5.45 +int is_from_user_enum_2(struct sip_msg* _msg, char* _suffix, char* _service);
    5.46 +
    5.47 +/*
    5.48 + * do source number destination routing.
    5.49 + * that is, make the ruri based on the from number
    5.50 + * this is like source ip policy routing
    5.51 + */
    5.52 +int enum_pv_query_1(struct sip_msg* _msg, char* _sp);
    5.53 +int enum_pv_query_2(struct sip_msg* _msg, char* _sp, char* _suffix);
    5.54 +int enum_pv_query_3(struct sip_msg* _msg, char* _sp, char* _suffix,
    5.55 +		    char* _service);
    5.56 +
    5.57 +/*
    5.58 + * Make enum query and if query succeeds, replace current uri with the
    5.59 + * result of the query
    5.60 + */
    5.61 +int enum_query_0(struct sip_msg* _msg, char* _str1, char* _str2);
    5.62 +int enum_query_1(struct sip_msg* _msg, char* _suffix, char* _str2);
    5.63 +int enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service);
    5.64 +
    5.65 +/*
    5.66 + * Infrastructure ENUM versions.
    5.67 + */
    5.68 +int i_enum_query_0(struct sip_msg* _msg, char* _str1, char* _str2);
    5.69 +int i_enum_query_1(struct sip_msg* _msg, char* _suffix, char* _str2);
    5.70 +int i_enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service);
    5.71 +
    5.72 +
    5.73 +#endif /* ENUM_H */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/opensips/modules/enum/enum_mod.c	Mon Jan 18 19:47:23 2010 +0100
     6.3 @@ -0,0 +1,157 @@
     6.4 +/*
     6.5 + * $Id: enum_mod.c 5976 2009-08-18 13:35:23Z bogdan_iancu $
     6.6 + *
     6.7 + * Enum module
     6.8 + *
     6.9 + * Copyright (C) 2002-2008 Juha Heinanen
    6.10 + *
    6.11 + * This file is part of opensips, a free SIP server.
    6.12 + *
    6.13 + * opensips is free software; you can redistribute it and/or modify
    6.14 + * it under the terms of the GNU General Public License as published by
    6.15 + * the Free Software Foundation; either version 2 of the License, or
    6.16 + * (at your option) any later version
    6.17 + *
    6.18 + * opensips is distributed in the hope that it will be useful,
    6.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.21 + * GNU General Public License for more details.
    6.22 + *
    6.23 + * You should have received a copy of the GNU General Public License 
    6.24 + * along with this program; if not, write to the Free Software 
    6.25 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.26 + *
    6.27 + * History:
    6.28 + * -------
    6.29 + * 2003-03-11: New module interface (janakj)
    6.30 + * 2003-03-16: flags export parameter added (janakj)
    6.31 + * 2003-12-15: added suffix parameter to enum_query (jh)
    6.32 + */
    6.33 +
    6.34 +
    6.35 +#include "enum_mod.h"
    6.36 +#include <stdio.h>
    6.37 +#include <stdlib.h>
    6.38 +#include "../../sr_module.h"
    6.39 +#include "../../error.h"
    6.40 +#include "../../mod_fix.h"
    6.41 +#include "enum.h"
    6.42 +
    6.43 +
    6.44 +
    6.45 +/*
    6.46 + * Module initialization function prototype
    6.47 + */
    6.48 +static int mod_init(void);
    6.49 +
    6.50 +
    6.51 +/*
    6.52 + * Module parameter variables
    6.53 + */
    6.54 +char* domain_suffix = "e164.arpa.";
    6.55 +char* tel_uri_params = "";
    6.56 +
    6.57 +char* branchlabel = "i";
    6.58 +char* i_enum_suffix = "e164.arpa.";
    6.59 +char* bl_algorithm = "cc";
    6.60 +
    6.61 +
    6.62 +/*
    6.63 + * Internal module variables
    6.64 + */
    6.65 +str suffix;
    6.66 +str param;
    6.67 +str service;
    6.68 +
    6.69 +str i_suffix;
    6.70 +str i_branchlabel;
    6.71 +str i_bl_alg;
    6.72 +
    6.73 +
    6.74 +/*
    6.75 + * Exported functions
    6.76 + */
    6.77 +static cmd_export_t cmds[] = {
    6.78 +	{"enum_query", (cmd_function)enum_query_0, 0, 0, 0, REQUEST_ROUTE},
    6.79 +	{"enum_query", (cmd_function)enum_query_1, 1, fixup_str_null,
    6.80 +	 fixup_free_str_null, REQUEST_ROUTE},
    6.81 +	{"enum_query", (cmd_function)enum_query_2, 2, fixup_str_str, 
    6.82 +	 fixup_free_str_str, REQUEST_ROUTE},
    6.83 +	{"enum_pv_query", (cmd_function)enum_pv_query_1, 1, fixup_pvar_null,
    6.84 +	 fixup_free_pvar_null, REQUEST_ROUTE},
    6.85 +	{"enum_pv_query", (cmd_function)enum_pv_query_2, 2, fixup_pvar_str,
    6.86 +	 fixup_free_pvar_str, REQUEST_ROUTE},
    6.87 +	{"enum_pv_query", (cmd_function)enum_pv_query_3, 3,
    6.88 +	 fixup_pvar_str_str, fixup_free_pvar_str_str, REQUEST_ROUTE},
    6.89 +	{"is_from_user_enum", (cmd_function)is_from_user_enum_0, 0, 0, 0,
    6.90 +	 REQUEST_ROUTE},
    6.91 +	{"is_from_user_enum", (cmd_function)is_from_user_enum_1, 1,
    6.92 +	 fixup_str_null, fixup_free_str_null, REQUEST_ROUTE},
    6.93 +	{"is_from_user_enum", (cmd_function)is_from_user_enum_2, 2,
    6.94 +	 fixup_str_str, fixup_free_str_str, REQUEST_ROUTE},
    6.95 +	{"i_enum_query", (cmd_function)i_enum_query_0, 0, 0, 0, REQUEST_ROUTE},
    6.96 +	{"i_enum_query", (cmd_function)i_enum_query_1, 1, fixup_str_null, 0,
    6.97 +	 REQUEST_ROUTE},
    6.98 +	{"i_enum_query", (cmd_function)i_enum_query_2, 2, fixup_str_str, 0,
    6.99 +	 REQUEST_ROUTE},
   6.100 +	{0, 0, 0, 0, 0, 0}
   6.101 +};
   6.102 +
   6.103 +
   6.104 +/*
   6.105 + * Exported parameters
   6.106 + */
   6.107 +static param_export_t params[] = {
   6.108 +	{"domain_suffix", STR_PARAM, &domain_suffix},
   6.109 +	{"tel_uri_params", STR_PARAM, &tel_uri_params},
   6.110 +	{"branchlabel", STR_PARAM, &branchlabel},
   6.111 +	{"i_enum_suffix", STR_PARAM, &i_enum_suffix},
   6.112 +	{"bl_algorithm", STR_PARAM, &bl_algorithm},
   6.113 +	{0, 0, 0}
   6.114 +};
   6.115 +
   6.116 +
   6.117 +/*
   6.118 + * Module parameter variables
   6.119 + */
   6.120 +struct module_exports exports = {
   6.121 +	"enum", 
   6.122 +	MODULE_VERSION,
   6.123 +	DEFAULT_DLFLAGS, /* dlopen flags */
   6.124 +	cmds,     /* Exported functions */
   6.125 +	params,   /* Exported parameters */
   6.126 +	0,        /* exported statistics */
   6.127 +	0,        /* exported MI functions */
   6.128 +	0,        /* exported pseudo-variables */
   6.129 +	0,        /* extra processes */
   6.130 +	mod_init, /* module initialization function */
   6.131 +	0,        /* response function*/
   6.132 +	0,        /* destroy function */
   6.133 +	0         /* per-child init function */
   6.134 +};
   6.135 +
   6.136 +
   6.137 +static int mod_init(void)
   6.138 +{
   6.139 +	LM_DBG("Initializing\n");
   6.140 +	
   6.141 +	suffix.s = domain_suffix;
   6.142 +	suffix.len = strlen(suffix.s);
   6.143 +
   6.144 +	param.s = tel_uri_params;
   6.145 +	param.len = strlen(param.s);
   6.146 +
   6.147 +	service.len = 0;
   6.148 +
   6.149 +	i_suffix.s = i_enum_suffix;
   6.150 +	i_suffix.len = strlen(i_enum_suffix);
   6.151 +
   6.152 +	i_branchlabel.s = branchlabel;
   6.153 +	i_branchlabel.len = strlen(branchlabel);
   6.154 +
   6.155 +	i_bl_alg.s = bl_algorithm;
   6.156 +	i_bl_alg.len = strlen(bl_algorithm);
   6.157 +
   6.158 +	return 0;
   6.159 +}
   6.160 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/opensips/modules/enum/enum_mod.h	Mon Jan 18 19:47:23 2010 +0100
     7.3 @@ -0,0 +1,45 @@
     7.4 +/*
     7.5 + * $Id: enum_mod.h 5901 2009-07-21 07:45:05Z bogdan_iancu $
     7.6 + *
     7.7 + * Enum module headers
     7.8 + *
     7.9 + * Copyright (C) 2002-2003 Juha Heinanen
    7.10 + *
    7.11 + * This file is part of opensips, a free SIP server.
    7.12 + *
    7.13 + * opensips is free software; you can redistribute it and/or modify
    7.14 + * it under the terms of the GNU General Public License as published by
    7.15 + * the Free Software Foundation; either version 2 of the License, or
    7.16 + * (at your option) any later version
    7.17 + *
    7.18 + * opensips is distributed in the hope that it will be useful,
    7.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.21 + * GNU General Public License for more details.
    7.22 + *
    7.23 + * You should have received a copy of the GNU General Public License 
    7.24 + * along with this program; if not, write to the Free Software 
    7.25 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.26 + */
    7.27 +
    7.28 +
    7.29 +#ifndef ENUM_MOD_H
    7.30 +#define ENUM_MOD_H
    7.31 +
    7.32 +
    7.33 +#include "../../str.h"
    7.34 +
    7.35 +
    7.36 +/*
    7.37 + * Internal module variables
    7.38 + */
    7.39 +extern str suffix;           /* str version of domain_suffix */
    7.40 +extern str param;            /* str version of tel_uri_params */
    7.41 +extern str service;          /* default (empty) service */
    7.42 +
    7.43 +extern str i_suffix;         /* suffix for infrastructure ENUM */
    7.44 +extern str i_branchlabel;    /* the label branching off the infrastructure tree */
    7.45 +extern str i_bl_alg;         /* how to know where to branch off */
    7.46 +
    7.47 +
    7.48 +#endif /* ENUM_MOD_H */

mercurial