2003-04-29 04:26:41 +00:00
/*
2005-09-14 20:46:50 +00:00
* Asterisk -- An open source telephony toolkit.
2003-04-29 04:26:41 +00:00
*
2006-02-14 22:18:13 +00:00
* Copyright (C) 1999 - 2006, Digium, Inc.
2003-04-29 04:26:41 +00:00
*
2005-09-14 20:46:50 +00:00
* Mark Spencer <markster@digium.com>
2003-05-01 04:29:25 +00:00
*
* Funding provided by nic.at
*
2005-09-14 20:46:50 +00:00
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
2005-10-24 20:12:06 +00:00
/*! \file
2005-09-14 20:46:50 +00:00
*
2005-10-24 20:12:06 +00:00
* \brief ENUM Support for Asterisk
2003-04-29 04:26:41 +00:00
*
2005-12-30 21:18:06 +00:00
* \author Mark Spencer <markster@digium.com>
*
* \arg Funding provided by nic.at
2006-04-05 06:43:14 +00:00
*
* \par Enum standards
*
* - NAPTR records: http://ietf.nri.reston.va.us/rfc/rfc2915.txt
* - DNS SRV records: http://www.ietf.org/rfc/rfc2782.txt
* - ENUM http://www.ietf.org/rfc/rfc3761.txt
* - ENUM for H.323: http://www.ietf.org/rfc/rfc3762.txt
* - ENUM SIP: http://www.ietf.org/rfc/rfc3764.txt
* - IANA ENUM Services: http://www.iana.org/assignments/enum-services
*
2012-03-22 19:51:16 +00:00
* - I-ENUM:
2008-05-09 19:54:45 +00:00
* http://tools.ietf.org/wg/enum/draft-ietf-enum-combined/
* http://tools.ietf.org/wg/enum/draft-ietf-enum-branch-location-record/
*
2006-04-05 13:53:06 +00:00
* \par Possible improvement
* \todo Implement a caching mechanism for multile enum lookups
2009-05-28 21:50:27 +00:00
* - See https://issues.asterisk.org/view.php?id=6739
2008-05-09 19:54:45 +00:00
* \todo The service type selection needs to be redone.
2003-04-29 04:26:41 +00:00
*/
2012-10-18 14:17:40 +00:00
/*! \li \ref enum.c uses the configuration file \ref enum.conf
* \addtogroup configuration_file Configuration Files
*/
/*!
* \page enum.conf enum.conf
* \verbinclude enum.conf.sample
*/
2012-06-15 16:20:16 +00:00
/*** MODULEINFO
<support_level>core</support_level>
***/
2006-06-07 18:54:56 +00:00
# include "asterisk.h"
2003-05-16 23:33:41 +00:00
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/nameser.h>
2007-02-18 15:03:42 +00:00
# ifdef __APPLE__
2003-10-27 20:00:41 +00:00
# include <arpa/nameser_compat.h>
# endif
2003-04-29 04:26:41 +00:00
# include <resolv.h>
2003-08-14 21:33:49 +00:00
# include <ctype.h>
# include <regex.h>
2003-04-29 04:26:41 +00:00
2005-04-21 06:02:45 +00:00
# include "asterisk/enum.h"
# include "asterisk/dns.h"
# include "asterisk/channel.h"
# include "asterisk/config.h"
# include "asterisk/utils.h"
2007-11-27 21:10:50 +00:00
# include "asterisk/manager.h"
2003-04-29 04:26:41 +00:00
2003-10-26 18:50:49 +00:00
# ifdef __APPLE__
# undef T_NAPTR
# define T_NAPTR 35
# endif
2004-05-16 18:12:16 +00:00
# ifdef __APPLE__
# undef T_TXT
# define T_TXT 16
# endif
2008-05-09 19:54:45 +00:00
static char ienum_branchlabel [ 32 ] = " i " ;
/* how to do infrastructure enum branch location resolution? */
# define ENUMLOOKUP_BLR_CC 0
# define ENUMLOOKUP_BLR_TXT 1
# define ENUMLOOKUP_BLR_EBL 2
static int ebl_alg = ENUMLOOKUP_BLR_CC ;
2012-03-22 19:51:16 +00:00
2008-05-09 19:54:45 +00:00
/* EBL record provisional type code */
# define T_EBL 65300
2003-04-29 04:26:41 +00:00
2008-05-09 19:54:45 +00:00
AST_MUTEX_DEFINE_STATIC ( enumlock ) ;
2003-05-01 04:29:25 +00:00
2008-05-09 19:54:45 +00:00
/*! \brief Determine the length of a country code when given an E.164 string */
/*
* Input: E.164 number w/o leading +
*
* Output: number of digits in the country code
2012-03-22 19:51:16 +00:00
* 0 on invalid number
2008-05-09 19:54:45 +00:00
*
* Algorithm:
* 3 digits is the default length of a country code.
* country codes 1 and 7 are a single digit.
* the following country codes are two digits: 20, 27, 30-34, 36, 39,
* 40, 41, 43-49, 51-58, 60-66, 81, 82, 84, 86, 90-95, 98.
*/
static int cclen ( const char * number )
{
int cc ;
char digits [ 3 ] = " " ;
2003-05-01 04:29:25 +00:00
2008-05-09 19:54:45 +00:00
if ( ! number | | ( strlen ( number ) < 3 ) ) {
return 0 ;
}
strncpy ( digits , number , 2 ) ;
2012-03-22 19:51:16 +00:00
2009-08-10 19:20:57 +00:00
if ( ! sscanf ( digits , " %30d " , & cc ) ) {
2008-05-09 19:54:45 +00:00
return 0 ;
}
if ( cc / 10 = = 1 | | cc / 10 = = 7 )
2012-03-22 19:51:16 +00:00
return 1 ;
2008-05-09 19:54:45 +00:00
if ( cc = = 20 | | cc = = 27 | | ( cc > = 30 & & cc < = 34 ) | | cc = = 36 | |
cc = = 39 | | cc = = 40 | | cc = = 41 | | ( cc > = 40 & & cc < = 41 ) | |
( cc > = 43 & & cc < = 49 ) | | ( cc > = 51 & & cc < = 58 ) | |
( cc > = 60 & & cc < = 66 ) | | cc = = 81 | | cc = = 82 | | cc = = 84 | |
cc = = 86 | | ( cc > = 90 & & cc < = 95 ) | | cc = = 98 ) {
return 2 ;
}
return 3 ;
}
struct txt_context {
char txt [ 1024 ] ; /* TXT record in TXT lookup */
int txtlen ; /* Length */
} ;
/*! \brief Callback for TXT record lookup, /ol version */
static int txt_callback ( void * context , unsigned char * answer , int len , unsigned char * fullanswer )
{
struct txt_context * c = context ;
unsigned int i ;
c - > txt [ 0 ] = 0 ; /* default to empty */
c - > txtlen = 0 ;
if ( answer = = NULL ) {
return 0 ;
}
2012-03-22 19:51:16 +00:00
/* RFC1035:
2008-05-09 19:54:45 +00:00
*
* <character-string> is a single length octet followed by that number of characters.
* TXT-DATA One or more <character-string>s.
*
* We only take the first string here.
*/
i = * answer + + ;
len - = 1 ;
if ( i > len ) { /* illegal packet */
ast_log ( LOG_WARNING , " txt_callback: malformed TXT record. \n " ) ;
return 0 ;
}
if ( i > = sizeof ( c - > txt ) ) { /* too long? */
ast_log ( LOG_WARNING , " txt_callback: TXT record too long. \n " ) ;
i = sizeof ( c - > txt ) - 1 ;
}
ast_copy_string ( c - > txt , ( char * ) answer , i + 1 ) ; /* this handles the \0 termination */
c - > txtlen = i ;
return 1 ;
}
/*! \brief Determine the branch location record as stored in a TXT record */
/*
* Input: CC code
*
2012-03-22 19:51:16 +00:00
* Output: number of digits in the number before the i-enum branch
2008-05-09 19:54:45 +00:00
*
* Algorithm: Build <ienum_branchlabel>.c.c.<suffix> and look for a TXT lookup.
2012-03-22 19:51:16 +00:00
* Return atoi(TXT-record).
* Return -1 on not found.
2008-05-09 19:54:45 +00:00
*
*/
static int blr_txt ( const char * cc , const char * suffix )
{
struct txt_context context ;
char domain [ 128 ] = " " ;
char * p1 , * p2 ;
int ret ;
ast_mutex_lock ( & enumlock ) ;
ast_verb ( 4 , " blr_txt() cc='%s', suffix='%s', c_bl='%s' \n " , cc , suffix , ienum_branchlabel ) ;
if ( sizeof ( domain ) < ( strlen ( cc ) * 2 + strlen ( ienum_branchlabel ) + strlen ( suffix ) + 2 ) ) {
ast_mutex_unlock ( & enumlock ) ;
ast_log ( LOG_WARNING , " ERROR: string sizing in blr_txt. \n " ) ;
return - 1 ;
}
p1 = domain + snprintf ( domain , sizeof ( domain ) , " %s. " , ienum_branchlabel ) ;
ast_mutex_unlock ( & enumlock ) ;
for ( p2 = ( char * ) cc + strlen ( cc ) - 1 ; p2 > = cc ; p2 - - ) {
if ( isdigit ( * p2 ) ) {
* p1 + + = * p2 ;
* p1 + + = ' . ' ;
}
}
strcat ( p1 , suffix ) ;
ast_verb ( 4 , " blr_txt() FQDN for TXT record: %s, cc was %s \n " , domain , cc ) ;
ret = ast_search_dns ( & context , domain , C_IN , T_TXT , txt_callback ) ;
if ( ret > 0 ) {
ret = atoi ( context . txt ) ;
if ( ( ret > = 0 ) & & ( ret < 20 ) ) {
ast_verb ( 3 , " blr_txt() BLR TXT record for %s is %d (apex: %s) \n " , cc , ret , suffix ) ;
return ret ;
}
}
2012-03-22 19:51:16 +00:00
2008-05-09 19:54:45 +00:00
ast_verb ( 3 , " blr_txt() BLR TXT record for %s not found (apex: %s) \n " , cc , suffix ) ;
return - 1 ;
}
struct ebl_context {
unsigned char pos ;
char separator [ 256 ] ; /* label to insert */
int sep_len ; /* Length */
char apex [ 256 ] ; /* new Apex */
int apex_len ; /* Length */
} ;
/*! \brief Callback for EBL record lookup */
static int ebl_callback ( void * context , unsigned char * answer , int len , unsigned char * fullanswer )
{
struct ebl_context * c = context ;
2015-04-09 12:57:21 +00:00
int i ;
2008-05-09 19:54:45 +00:00
c - > pos = 0 ; /* default to empty */
c - > separator [ 0 ] = 0 ;
c - > sep_len = 0 ;
2012-03-22 19:51:16 +00:00
c - > apex [ 0 ] = 0 ;
2008-05-09 19:54:45 +00:00
c - > apex_len = 0 ;
if ( answer = = NULL ) {
return 0 ;
}
/* draft-lendl-enum-branch-location-record-00
*
* 0 1 2 3 4 5 6 7
* +--+--+--+--+--+--+--+--+
* | POSITION |
* +--+--+--+--+--+--+--+--+
* / SEPARATOR /
* +--+--+--+--+--+--+--+--+
* / APEX /
* +--+--+--+--+--+--+--+--+
*
* where POSITION is a single byte, SEPARATOR is a <character-string>
2012-03-22 19:51:16 +00:00
* and APEX is a <domain-name>.
*
2008-05-09 19:54:45 +00:00
*/
c - > pos = * answer + + ;
len - = 1 ;
if ( ( c - > pos > 15 ) | | len < 2 ) { /* illegal packet */
ast_log ( LOG_WARNING , " ebl_callback: malformed EBL record. \n " ) ;
return 0 ;
}
i = * answer + + ;
len - = 1 ;
if ( i > len ) { /* illegal packet */
ast_log ( LOG_WARNING , " ebl_callback: malformed EBL record. \n " ) ;
return 0 ;
}
ast_copy_string ( c - > separator , ( char * ) answer , i + 1 ) ;
c - > sep_len = i ;
answer + = i ;
len - = i ;
2012-03-22 19:51:16 +00:00
if ( ( i = dn_expand ( ( unsigned char * ) fullanswer , ( unsigned char * ) answer + len ,
2008-05-09 19:54:45 +00:00
( unsigned char * ) answer , c - > apex , sizeof ( c - > apex ) - 1 ) ) < 0 ) {
ast_log ( LOG_WARNING , " Failed to expand hostname \n " ) ;
return 0 ;
}
c - > apex [ i ] = 0 ;
c - > apex_len = i ;
return 1 ;
}
/*! \brief Evaluate the I-ENUM branch as stored in an EBL record */
/*
* Input: CC code
*
2012-03-22 19:51:16 +00:00
* Output: number of digits in the number before the i-enum branch
2008-05-09 19:54:45 +00:00
*
2012-03-22 19:51:16 +00:00
* Algorithm: Build <ienum_branchlabel>.c.c.<suffix> and look for an EBL record
* Return pos and fill in separator and apex.
* Return -1 on not found.
2008-05-09 19:54:45 +00:00
*
*/
static int blr_ebl ( const char * cc , const char * suffix , char * separator , int sep_len , char * apex , int apex_len )
{
struct ebl_context context ;
char domain [ 128 ] = " " ;
char * p1 , * p2 ;
int ret ;
ast_mutex_lock ( & enumlock ) ;
ast_verb ( 4 , " blr_ebl() cc='%s', suffix='%s', c_bl='%s' \n " , cc , suffix , ienum_branchlabel ) ;
if ( sizeof ( domain ) < ( strlen ( cc ) * 2 + strlen ( ienum_branchlabel ) + strlen ( suffix ) + 2 ) ) {
ast_mutex_unlock ( & enumlock ) ;
ast_log ( LOG_WARNING , " ERROR: string sizing in blr_EBL. \n " ) ;
return - 1 ;
}
p1 = domain + snprintf ( domain , sizeof ( domain ) , " %s. " , ienum_branchlabel ) ;
ast_mutex_unlock ( & enumlock ) ;
for ( p2 = ( char * ) cc + strlen ( cc ) - 1 ; p2 > = cc ; p2 - - ) {
if ( isdigit ( * p2 ) ) {
* p1 + + = * p2 ;
* p1 + + = ' . ' ;
}
}
strcat ( p1 , suffix ) ;
ast_verb ( 4 , " blr_ebl() FQDN for EBL record: %s, cc was %s \n " , domain , cc ) ;
ret = ast_search_dns ( & context , domain , C_IN , T_EBL , ebl_callback ) ;
if ( ret > 0 ) {
ret = context . pos ;
if ( ( ret > = 0 ) & & ( ret < 20 ) ) {
ast_verb ( 3 , " blr_txt() BLR EBL record for %s is %d/%s/%s) \n " , cc , ret , context . separator , context . apex ) ;
ast_copy_string ( separator , context . separator , sep_len ) ;
ast_copy_string ( apex , context . apex , apex_len ) ;
return ret ;
}
}
ast_verb ( 3 , " blr_txt() BLR EBL record for %s not found (apex: %s) \n " , cc , suffix ) ;
return - 1 ;
}
2003-04-29 04:26:41 +00:00
2006-01-20 00:18:42 +00:00
/*! \brief Parse NAPTR record information elements */
2006-07-07 06:55:48 +00:00
static unsigned int parse_ie ( char * data , unsigned int maxdatalen , unsigned char * src , unsigned int srclen )
2003-04-29 04:26:41 +00:00
{
2006-05-18 19:39:39 +00:00
unsigned int len , olen ;
2005-03-02 05:17:13 +00:00
2006-05-18 19:39:39 +00:00
len = olen = ( unsigned int ) src [ 0 ] ;
2003-04-29 04:26:41 +00:00
src + + ;
srclen - - ;
2006-05-18 19:39:39 +00:00
if ( len > srclen ) {
2014-05-09 22:49:26 +00:00
ast_log ( LOG_WARNING , " ENUM parsing failed: Wanted %u characters, got %u \n " , len , srclen ) ;
2003-04-29 04:26:41 +00:00
return - 1 ;
}
2006-05-18 19:39:39 +00:00
2003-04-29 04:26:41 +00:00
if ( len > maxdatalen )
len = maxdatalen ;
memcpy ( data , src , len ) ;
2006-05-18 19:39:39 +00:00
2003-04-29 04:26:41 +00:00
return olen + 1 ;
}
2006-01-20 00:18:42 +00:00
/*! \brief Parse DNS NAPTR record used in ENUM ---*/
2008-05-09 19:54:45 +00:00
static int parse_naptr ( unsigned char * dst , int dstsize , char * tech , int techsize , unsigned char * answer , int len , unsigned char * naptrinput )
2003-04-29 04:26:41 +00:00
{
2005-09-23 02:40:38 +00:00
char tech_return [ 80 ] ;
2008-05-09 19:54:45 +00:00
char * oanswer = ( char * ) answer ;
2005-08-11 18:05:25 +00:00
char flags [ 512 ] = " " ;
char services [ 512 ] = " " ;
2005-09-23 02:40:38 +00:00
char * p ;
2005-08-11 18:05:25 +00:00
char regexp [ 512 ] = " " ;
char repl [ 512 ] = " " ;
2009-03-06 17:26:38 +00:00
char tempdst [ 512 ] = " " ;
2008-05-09 19:54:45 +00:00
char errbuff [ 512 ] = " " ;
2005-08-07 06:34:26 +00:00
char delim ;
char * delim2 ;
2009-03-06 17:26:38 +00:00
char * pattern , * subst , * d ;
2003-04-29 04:26:41 +00:00
int res ;
2008-05-09 19:54:45 +00:00
int regexp_len , rc ;
2009-03-06 17:26:38 +00:00
static const int max_bt = 10 ; /* max num of regexp backreference allowed, must remain 10 to guarantee a valid backreference index */
int size , matchindex ; /* size is the size of the backreference sub. */
size_t d_len = sizeof ( tempdst ) - 1 ;
2003-08-14 21:33:49 +00:00
regex_t preg ;
2009-03-06 17:26:38 +00:00
regmatch_t pmatch [ max_bt ] ;
2003-08-14 21:33:49 +00:00
2005-09-23 02:40:38 +00:00
tech_return [ 0 ] = ' \0 ' ;
2004-07-14 07:44:19 +00:00
dst [ 0 ] = ' \0 ' ;
2005-09-14 01:36:15 +00:00
2003-04-29 04:26:41 +00:00
if ( len < sizeof ( struct naptr ) ) {
2005-03-02 05:17:13 +00:00
ast_log ( LOG_WARNING , " NAPTR record length too short \n " ) ;
2003-04-29 04:26:41 +00:00
return - 1 ;
}
answer + = sizeof ( struct naptr ) ;
len - = sizeof ( struct naptr ) ;
if ( ( res = parse_ie ( flags , sizeof ( flags ) - 1 , answer , len ) ) < 0 ) {
2005-03-02 05:17:13 +00:00
ast_log ( LOG_WARNING , " Failed to get flags from NAPTR record \n " ) ;
2005-09-23 02:40:38 +00:00
return - 1 ;
} else {
answer + = res ;
len - = res ;
2005-03-02 05:17:13 +00:00
}
2008-05-09 19:54:45 +00:00
2003-04-29 04:26:41 +00:00
if ( ( res = parse_ie ( services , sizeof ( services ) - 1 , answer , len ) ) < 0 ) {
2005-03-02 05:17:13 +00:00
ast_log ( LOG_WARNING , " Failed to get services from NAPTR record \n " ) ;
2005-09-23 02:40:38 +00:00
return - 1 ;
} else {
answer + = res ;
len - = res ;
2005-03-02 05:17:13 +00:00
}
if ( ( res = parse_ie ( regexp , sizeof ( regexp ) - 1 , answer , len ) ) < 0 ) {
ast_log ( LOG_WARNING , " Failed to get regexp from NAPTR record \n " ) ;
2005-09-23 02:40:38 +00:00
return - 1 ;
} else {
answer + = res ;
len - = res ;
2005-03-02 05:17:13 +00:00
}
2005-09-14 01:36:15 +00:00
2008-05-09 19:54:45 +00:00
if ( ( res = dn_expand ( ( unsigned char * ) oanswer , ( unsigned char * ) answer + len , ( unsigned char * ) answer , repl , sizeof ( repl ) - 1 ) ) < 0 ) {
2003-04-29 04:26:41 +00:00
ast_log ( LOG_WARNING , " Failed to expand hostname \n " ) ;
return - 1 ;
2005-09-23 02:40:38 +00:00
}
2009-03-06 17:26:38 +00:00
2007-06-14 19:39:12 +00:00
ast_debug ( 3 , " NAPTR input='%s', flags='%s', services='%s', regexp='%s', repl='%s' \n " ,
naptrinput , flags , services , regexp , repl ) ;
2003-08-14 21:33:49 +00:00
2008-05-09 19:54:45 +00:00
2003-08-14 21:33:49 +00:00
if ( tolower ( flags [ 0 ] ) ! = ' u ' ) {
2005-03-02 05:17:13 +00:00
ast_log ( LOG_WARNING , " NAPTR Flag must be 'U' or 'u'. \n " ) ;
2003-08-14 21:33:49 +00:00
return - 1 ;
}
2005-09-23 02:40:38 +00:00
p = strstr ( services , " e2u+ " ) ;
if ( p = = NULL )
p = strstr ( services , " E2U+ " ) ;
if ( p ) {
p = p + 4 ;
if ( strchr ( p , ' : ' ) ) {
p = strchr ( p , ' : ' ) + 1 ;
}
ast_copy_string ( tech_return , p , sizeof ( tech_return ) ) ;
2003-10-04 21:58:16 +00:00
} else {
2005-09-14 01:36:15 +00:00
2005-09-23 02:40:38 +00:00
p = strstr ( services , " +e2u " ) ;
if ( p = = NULL )
p = strstr ( services , " +E2U " ) ;
if ( p ) {
* p = 0 ;
p = strchr ( services , ' : ' ) ;
if ( p )
* p = 0 ;
ast_copy_string ( tech_return , services , sizeof ( tech_return ) ) ;
}
2003-08-14 21:33:49 +00:00
}
regexp_len = strlen ( regexp ) ;
if ( regexp_len < 7 ) {
ast_log ( LOG_WARNING , " Regex too short to be meaningful. \n " ) ;
return - 1 ;
2005-09-23 02:40:38 +00:00
}
2003-08-14 21:33:49 +00:00
2012-03-22 19:51:16 +00:00
/* this takes the first character of the regexp (which is a delimiter)
2009-03-06 17:26:38 +00:00
* and uses that character to find the index of the second delimiter */
2003-08-14 21:33:49 +00:00
delim = regexp [ 0 ] ;
delim2 = strchr ( regexp + 1 , delim ) ;
2009-03-06 17:26:38 +00:00
if ( ( delim2 = = NULL ) | | ( regexp [ regexp_len - 1 ] ! = delim ) ) { /* is the second delimiter found, and is the end of the regexp a delimiter */
ast_log ( LOG_WARNING , " Regex delimiter error (on \" %s \" ). \n " , regexp ) ;
return - 1 ;
} else if ( strchr ( ( delim2 + 1 ) , delim ) = = NULL ) { /* if the second delimiter is found, make sure there is a third instance. this could be the end one instead of the middle */
2008-03-04 23:04:29 +00:00
ast_log ( LOG_WARNING , " Regex delimiter error (on \" %s \" ). \n " , regexp ) ;
2003-08-14 21:33:49 +00:00
return - 1 ;
}
2009-03-06 17:26:38 +00:00
pattern = regexp + 1 ; /* pattern is the regex without the begining and ending delimiter */
* delim2 = 0 ; /* zero out the middle delimiter */
subst = delim2 + 1 ; /* dst substring is everything after the second delimiter. */
regexp [ regexp_len - 1 ] = 0 ; /* zero out the last delimiter */
2003-08-14 21:33:49 +00:00
/*
* now do the regex wizardry.
*/
if ( regcomp ( & preg , pattern , REG_EXTENDED | REG_NEWLINE ) ) {
2008-03-04 23:04:29 +00:00
ast_log ( LOG_WARNING , " NAPTR Regex compilation error (regex = \" %s \" ). \n " , regexp ) ;
2003-08-14 21:33:49 +00:00
return - 1 ;
}
2009-03-06 17:26:38 +00:00
if ( preg . re_nsub > ARRAY_LEN ( pmatch ) ) {
2005-03-02 05:17:13 +00:00
ast_log ( LOG_WARNING , " NAPTR Regex compilation error: too many subs. \n " ) ;
2003-08-14 21:33:49 +00:00
regfree ( & preg ) ;
return - 1 ;
}
2009-03-06 17:26:38 +00:00
/* pmatch is an array containing the substring indexes for the regex backreference sub.
* max_bt is the maximum number of backreferences allowed to be stored in pmatch */
if ( ( rc = regexec ( & preg , ( char * ) naptrinput , max_bt , pmatch , 0 ) ) ) {
2008-05-09 19:54:45 +00:00
regerror ( rc , & preg , errbuff , sizeof ( errbuff ) ) ;
ast_log ( LOG_WARNING , " NAPTR Regex match failed. Reason: %s \n " , errbuff ) ;
2003-08-14 21:33:49 +00:00
regfree ( & preg ) ;
return - 1 ;
}
regfree ( & preg ) ;
2009-03-06 17:26:38 +00:00
d = tempdst ;
2005-09-23 02:40:38 +00:00
d_len - - ;
2009-03-06 17:26:38 +00:00
/* perform the backreference sub. Search the subst for backreferences,
* when a backreference is found, retrieve the backreferences number.
* use the backreference number as an index for pmatch to retrieve the
* beginning and ending indexes of the substring to insert as the backreference.
* if no backreference is found, continue copying the subst into tempdst */
2005-09-23 02:40:38 +00:00
while ( * subst & & ( d_len > 0 ) ) {
2009-03-06 17:26:38 +00:00
if ( ( subst [ 0 ] = = ' \\ ' ) & & isdigit ( subst [ 1 ] ) ) { /* is this character the beginning of a backreference */
matchindex = ( int ) ( subst [ 1 ] - ' 0 ' ) ;
if ( matchindex > = ARRAY_LEN ( pmatch ) ) {
ast_log ( LOG_WARNING , " Error during regex substitution. Invalid pmatch index. \n " ) ;
return - 1 ;
}
/* pmatch len is 10. we are garanteed a single char 0-9 is a valid index */
size = pmatch [ matchindex ] . rm_eo - pmatch [ matchindex ] . rm_so ;
2003-08-14 21:33:49 +00:00
if ( size > d_len ) {
2005-03-02 05:17:13 +00:00
ast_log ( LOG_WARNING , " Not enough space during NAPTR regex substitution. \n " ) ;
2003-08-14 21:33:49 +00:00
return - 1 ;
2008-05-09 19:54:45 +00:00
}
2009-03-06 17:26:38 +00:00
/* are the pmatch indexes valid for the input length */
if ( ( strlen ( ( char * ) naptrinput ) > = pmatch [ matchindex ] . rm_eo ) & & ( pmatch [ matchindex ] . rm_so < = pmatch [ matchindex ] . rm_eo ) ) {
memcpy ( d , ( naptrinput + ( int ) pmatch [ matchindex ] . rm_so ) , size ) ; /* copy input substring into backreference marker */
d_len - = size ;
subst + = 2 ; /* skip over backreference characters to next valid character */
d + = size ;
} else {
ast_log ( LOG_WARNING , " Error during regex substitution. Invalid backreference index. \n " ) ;
return - 1 ;
}
2003-08-14 21:33:49 +00:00
} else if ( isprint ( * subst ) ) {
* d + + = * subst + + ;
d_len - - ;
} else {
ast_log ( LOG_WARNING , " Error during regex substitution. \n " ) ;
return - 1 ;
2003-04-29 04:26:41 +00:00
}
2003-08-14 21:33:49 +00:00
}
* d = 0 ;
2009-03-06 17:26:38 +00:00
ast_copy_string ( ( char * ) dst , tempdst , dstsize ) ;
2004-07-14 07:44:19 +00:00
dst [ dstsize - 1 ] = ' \0 ' ;
2005-09-14 01:36:15 +00:00
2005-09-23 02:40:38 +00:00
if ( * tech ! = ' \0 ' ) { /* check if it is requested NAPTR */
if ( ! strncasecmp ( tech , " ALL " , techsize ) ) {
2008-05-09 19:54:45 +00:00
return 0 ; /* return or count any RR */
2005-09-23 02:40:38 +00:00
}
2008-05-09 19:54:45 +00:00
if ( ! strncasecmp ( tech_return , tech , sizeof ( tech_return ) < techsize ? sizeof ( tech_return ) : techsize ) ) {
2005-09-23 02:40:38 +00:00
ast_copy_string ( tech , tech_return , techsize ) ;
2008-05-09 19:54:45 +00:00
return 0 ; /* we got our RR */
2005-09-23 02:40:38 +00:00
} else { /* go to the next RR in the DNS answer */
2008-05-09 19:54:45 +00:00
return 1 ;
2005-09-23 02:40:38 +00:00
}
}
2005-09-14 01:36:15 +00:00
2005-09-23 02:40:38 +00:00
/* tech was not specified, return first parsed RR */
ast_copy_string ( tech , tech_return , techsize ) ;
2005-09-14 01:36:15 +00:00
2008-05-09 19:54:45 +00:00
return 0 ;
2003-04-29 04:26:41 +00:00
}
2005-09-14 01:36:15 +00:00
/* do not return requested value, just count RRs and return thei number in dst */
# define ENUMLOOKUP_OPTIONS_COUNT 1
2008-05-09 19:54:45 +00:00
/* do an ISN style lookup */
# define ENUMLOOKUP_OPTIONS_ISN 2
/* do a infrastructure ENUM lookup */
# define ENUMLOOKUP_OPTIONS_IENUM 4
/* do a direct DNS lookup: no reversal */
# define ENUMLOOKUP_OPTIONS_DIRECT 8
2004-05-16 18:12:16 +00:00
2006-01-20 00:18:42 +00:00
/*! \brief Callback from ENUM lookup function */
2006-07-07 06:55:48 +00:00
static int enum_callback ( void * context , unsigned char * answer , int len , unsigned char * fullanswer )
2003-04-29 04:26:41 +00:00
{
2006-07-13 20:14:27 +00:00
struct enum_context * c = context ;
void * p = NULL ;
int res ;
2003-09-27 00:22:46 +00:00
2008-05-09 19:54:45 +00:00
res = parse_naptr ( ( unsigned char * ) c - > dst , c - > dstlen , c - > tech , c - > techlen , answer , len , ( unsigned char * ) c - > naptrinput ) ;
2005-09-14 01:36:15 +00:00
2006-07-13 20:14:27 +00:00
if ( res < 0 ) {
2008-05-09 19:54:45 +00:00
ast_log ( LOG_WARNING , " Failed to parse naptr \n " ) ;
2004-03-03 03:12:59 +00:00
return - 1 ;
2008-05-09 19:54:45 +00:00
} else if ( ( res = = 0 ) & & ! ast_strlen_zero ( c - > dst ) ) { /* ok, we got needed NAPTR */
if ( c - > options & ENUMLOOKUP_OPTIONS_COUNT ) { /* counting RRs */
c - > count + + ;
snprintf ( c - > dst , c - > dstlen , " %d " , c - > count ) ;
2006-07-13 20:14:27 +00:00
} else {
if ( ( p = ast_realloc ( c - > naptr_rrs , sizeof ( * c - > naptr_rrs ) * ( c - > naptr_rrs_count + 1 ) ) ) ) {
c - > naptr_rrs = p ;
memcpy ( & c - > naptr_rrs [ c - > naptr_rrs_count ] . naptr , answer , sizeof ( c - > naptr_rrs - > naptr ) ) ;
2007-06-14 23:01:01 +00:00
c - > naptr_rrs [ c - > naptr_rrs_count ] . result = ast_strdup ( c - > dst ) ;
c - > naptr_rrs [ c - > naptr_rrs_count ] . tech = ast_strdup ( c - > tech ) ;
2006-07-13 20:14:27 +00:00
c - > naptr_rrs [ c - > naptr_rrs_count ] . sort_pos = c - > naptr_rrs_count ;
c - > naptr_rrs_count + + ;
}
c - > dst [ 0 ] = 0 ;
}
return 0 ;
2004-03-03 03:12:59 +00:00
}
2003-09-27 00:22:46 +00:00
2003-04-29 04:26:41 +00:00
return 0 ;
}
2007-07-23 14:32:04 +00:00
/* ENUM lookup */
2007-05-15 23:05:20 +00:00
int ast_get_enum ( struct ast_channel * chan , const char * number , char * dst , int dstlen , char * tech , int techlen , char * suffix , char * options , unsigned int record , struct enum_context * * argcontext )
2003-04-29 04:26:41 +00:00
{
2007-05-15 23:05:20 +00:00
struct enum_context * context ;
2008-05-09 19:54:45 +00:00
char tmp [ 512 ] ;
char domain [ 256 ] ;
char left [ 128 ] ;
char middle [ 128 ] ;
char naptrinput [ 128 ] ;
char apex [ 128 ] = " " ;
2003-04-29 04:26:41 +00:00
int ret = - 1 ;
2005-09-23 02:40:38 +00:00
/* for ISN rewrite */
char * p1 = NULL ;
char * p2 = NULL ;
2008-05-09 19:54:45 +00:00
char * p3 = NULL ;
2005-09-23 02:40:38 +00:00
int k = 0 ;
int i = 0 ;
int z = 0 ;
2008-05-09 19:54:45 +00:00
int spaceleft = 0 ;
struct timeval time_start , time_end ;
2011-07-25 19:57:27 +00:00
2008-05-09 19:54:45 +00:00
if ( ast_strlen_zero ( suffix ) ) {
ast_log ( LOG_WARNING , " ast_get_enum need a suffix parameter now. \n " ) ;
return - 1 ;
}
2014-05-09 22:49:26 +00:00
ast_debug ( 2 , " num='%s', tech='%s', suffix='%s', options='%s', record=%u \n " , number , tech , suffix , options , record ) ;
2008-05-09 19:54:45 +00:00
/*
We don't need that any more, that "n" preceding the number has been replaced by a flag
in the options paramter.
ast_copy_string(naptrinput, number, sizeof(naptrinput));
*/
/*
* The "number" parameter includes a leading '+' if it's a full E.164 number (and not ISN)
* We need to preserve that as the regex inside NAPTRs expect the +.
*
* But for the domain generation, the '+' is a nuissance, so we get rid of it.
*/
ast_copy_string ( naptrinput , number [ 0 ] = = ' n ' ? number + 1 : number , sizeof ( naptrinput ) ) ;
if ( number [ 0 ] = = ' + ' ) {
number + + ;
}
2005-09-23 02:40:38 +00:00
2011-07-25 19:57:27 +00:00
if ( ! ( context = ast_calloc ( 1 , sizeof ( * context ) ) ) ) {
2007-05-15 23:05:20 +00:00
return - 1 ;
2011-07-25 19:57:27 +00:00
}
2007-05-15 23:05:20 +00:00
2011-07-25 19:57:27 +00:00
if ( ( p3 = strchr ( naptrinput , ' * ' ) ) ) {
* p3 = ' \0 ' ;
2008-05-09 19:54:45 +00:00
}
2003-08-14 21:33:49 +00:00
2007-05-15 23:05:20 +00:00
context - > naptrinput = naptrinput ; /* The number */
context - > dst = dst ; /* Return string */
context - > dstlen = dstlen ;
context - > tech = tech ;
context - > techlen = techlen ;
context - > options = 0 ;
2008-05-09 19:54:45 +00:00
context - > position = record > 0 ? record : 1 ;
context - > count = 0 ;
2007-05-15 23:05:20 +00:00
context - > naptr_rrs = NULL ;
context - > naptr_rrs_count = 0 ;
2005-09-23 02:40:38 +00:00
2008-05-09 19:54:45 +00:00
/*
* Process options:
*
2012-03-22 19:51:16 +00:00
* c Return count, not URI
* i Use infrastructure ENUM
* s Do ISN transformation
* d Direct DNS query: no reversing.
2008-05-09 19:54:45 +00:00
*
*/
2006-04-04 19:48:42 +00:00
if ( options ! = NULL ) {
2008-05-09 19:54:45 +00:00
if ( strchr ( options , ' s ' ) ) {
context - > options | = ENUMLOOKUP_OPTIONS_ISN ;
} else if ( strchr ( options , ' i ' ) ) {
context - > options | = ENUMLOOKUP_OPTIONS_IENUM ;
} else if ( strchr ( options , ' d ' ) ) {
context - > options | = ENUMLOOKUP_OPTIONS_DIRECT ;
}
if ( strchr ( options , ' c ' ) ) {
context - > options | = ENUMLOOKUP_OPTIONS_COUNT ;
}
if ( strchr ( number , ' * ' ) ) {
context - > options | = ENUMLOOKUP_OPTIONS_ISN ;
2005-09-23 02:40:38 +00:00
}
}
2011-07-25 19:57:27 +00:00
ast_debug ( 2 , " ENUM options(%s): pos=%d, options='%d' \n " , options , context - > position , context - > options ) ;
ast_debug ( 1 , " n='%s', tech='%s', suffix='%s', options='%d', record='%d' \n " ,
2007-05-15 23:05:20 +00:00
number , tech , suffix , context - > options , context - > position ) ;
2006-10-31 11:01:06 +00:00
2008-05-09 19:54:45 +00:00
/*
2012-03-22 19:51:16 +00:00
* This code does more than simple RFC3261 ENUM. All these rewriting
2008-05-09 19:54:45 +00:00
* schemes have in common that they build the FQDN for the NAPTR lookup
* by concatenating
* - a number which needs be flipped and "."-seperated (left)
* - some fixed string (middle)
* - an Apex. (apex)
*
* The RFC3261 ENUM is: left=full number, middle="", apex=from args.
* ISN: number = "middle*left", apex=from args
* I-ENUM: EBL parameters build the split, can change apex
* Direct: left="", middle=argument, apex=from args
*
*/
/* default: the whole number will be flipped, no middle domain component */
ast_copy_string ( left , number , sizeof ( left ) ) ;
middle [ 0 ] = ' \0 ' ;
/*
2012-03-22 19:51:16 +00:00
* I-ENUM can change the apex, thus we copy it
2008-05-09 19:54:45 +00:00
*/
ast_copy_string ( apex , suffix , sizeof ( apex ) ) ;
2005-09-23 02:40:38 +00:00
/* ISN rewrite */
2008-05-09 19:54:45 +00:00
if ( ( context - > options & ENUMLOOKUP_OPTIONS_ISN ) & & ( p1 = strchr ( number , ' * ' ) ) ) {
* p1 + + = ' \0 ' ;
ast_copy_string ( left , number , sizeof ( left ) ) ;
ast_copy_string ( middle , p1 , sizeof ( middle ) - 1 ) ;
strcat ( middle , " . " ) ;
2011-07-25 19:57:27 +00:00
ast_debug ( 2 , " ISN ENUM: left=%s, middle='%s' \n " , left , middle ) ;
2008-05-09 19:54:45 +00:00
/* Direct DNS lookup rewrite */
} else if ( context - > options & ENUMLOOKUP_OPTIONS_DIRECT ) {
left [ 0 ] = 0 ; /* nothing to flip around */
ast_copy_string ( middle , number , sizeof ( middle ) - 1 ) ;
strcat ( middle , " . " ) ;
2011-07-25 19:57:27 +00:00
ast_debug ( 2 , " DIRECT ENUM: middle='%s' \n " , middle ) ;
2008-05-09 19:54:45 +00:00
/* Infrastructure ENUM rewrite */
} else if ( context - > options & ENUMLOOKUP_OPTIONS_IENUM ) {
int sdl = 0 ;
char cc [ 8 ] ;
char sep [ 256 ] , n_apex [ 256 ] ;
int cc_len = cclen ( number ) ;
sdl = cc_len ;
ast_mutex_lock ( & enumlock ) ;
ast_copy_string ( sep , ienum_branchlabel , sizeof ( sep ) ) ; /* default */
ast_mutex_unlock ( & enumlock ) ;
2005-09-14 01:36:15 +00:00
2008-05-09 19:54:45 +00:00
switch ( ebl_alg ) {
case ENUMLOOKUP_BLR_EBL :
ast_copy_string ( cc , number , cc_len ) ; /* cclen() never returns more than 3 */
sdl = blr_ebl ( cc , suffix , sep , sizeof ( sep ) - 1 , n_apex , sizeof ( n_apex ) - 1 ) ;
2005-09-14 01:36:15 +00:00
2008-05-09 19:54:45 +00:00
if ( sdl > = 0 ) {
ast_copy_string ( apex , n_apex , sizeof ( apex ) ) ;
2011-07-25 19:57:27 +00:00
ast_debug ( 2 , " EBL ENUM: sep=%s, apex='%s' \n " , sep , n_apex ) ;
2008-05-09 19:54:45 +00:00
} else {
sdl = cc_len ;
2005-09-23 02:40:38 +00:00
}
2008-05-09 19:54:45 +00:00
break ;
case ENUMLOOKUP_BLR_TXT :
ast_copy_string ( cc , number , cc_len ) ; /* cclen() never returns more than 3 */
sdl = blr_txt ( cc , suffix ) ;
2011-07-25 19:57:27 +00:00
if ( sdl < 0 ) {
2008-05-09 19:54:45 +00:00
sdl = cc_len ;
2011-07-25 19:57:27 +00:00
}
2008-05-09 19:54:45 +00:00
break ;
case ENUMLOOKUP_BLR_CC : /* BLR is at the country-code level */
default :
sdl = cc_len ;
break ;
2005-09-23 02:40:38 +00:00
}
2005-09-14 01:36:15 +00:00
2008-05-09 19:54:45 +00:00
if ( sdl > strlen ( number ) ) { /* Number too short for this sdl? */
ast_log ( LOG_WARNING , " I-ENUM: subdomain location %d behind number %s \n " , sdl , number ) ;
2012-05-18 14:43:44 +00:00
ast_free ( context ) ;
2008-05-09 19:54:45 +00:00
return 0 ;
}
ast_copy_string ( left , number + sdl , sizeof ( left ) ) ;
ast_mutex_lock ( & enumlock ) ;
ast_copy_string ( middle , sep , sizeof ( middle ) - 1 ) ;
strcat ( middle , " . " ) ;
ast_mutex_unlock ( & enumlock ) ;
/* check the space we need for middle */
if ( ( sdl * 2 + strlen ( middle ) + 2 ) > sizeof ( middle ) ) {
ast_log ( LOG_WARNING , " ast_get_enum: not enough space for I-ENUM rewrite. \n " ) ;
2012-05-18 14:43:44 +00:00
ast_free ( context ) ;
2008-05-09 19:54:45 +00:00
return - 1 ;
}
p1 = middle + strlen ( middle ) ;
for ( p2 = ( char * ) number + sdl - 1 ; p2 > = number ; p2 - - ) {
if ( isdigit ( * p2 ) ) {
* p1 + + = * p2 ;
* p1 + + = ' . ' ;
2005-09-23 02:40:38 +00:00
}
2008-05-09 19:54:45 +00:00
}
* p1 = ' \0 ' ;
2011-07-25 19:57:27 +00:00
ast_debug ( 2 , " I-ENUM: cclen=%d, left=%s, middle='%s', apex='%s' \n " , cc_len , left , middle , apex ) ;
2008-05-09 19:54:45 +00:00
}
if ( strlen ( left ) * 2 + 2 > sizeof ( domain ) ) {
ast_log ( LOG_WARNING , " string to long in ast_get_enum \n " ) ;
2012-05-18 14:43:44 +00:00
ast_free ( context ) ;
2008-05-09 19:54:45 +00:00
return - 1 ;
}
/* flip left into domain */
p1 = domain ;
for ( p2 = left + strlen ( left ) ; p2 > = left ; p2 - - ) {
if ( isdigit ( * p2 ) ) {
* p1 + + = * p2 ;
* p1 + + = ' . ' ;
2005-09-23 02:40:38 +00:00
}
2003-04-29 04:26:41 +00:00
}
2008-05-09 19:54:45 +00:00
* p1 = ' \0 ' ;
2005-09-14 01:36:15 +00:00
2007-05-15 23:05:20 +00:00
if ( chan & & ast_autoservice_start ( chan ) < 0 ) {
2007-06-06 21:20:11 +00:00
ast_free ( context ) ;
2003-09-27 00:22:46 +00:00
return - 1 ;
2007-05-15 23:05:20 +00:00
}
2003-09-27 00:22:46 +00:00
2008-05-09 19:54:45 +00:00
spaceleft = sizeof ( tmp ) - 2 ;
ast_copy_string ( tmp , domain , spaceleft ) ;
spaceleft - = strlen ( domain ) ;
2006-10-31 11:01:06 +00:00
2008-05-09 19:54:45 +00:00
if ( * middle ) {
strncat ( tmp , middle , spaceleft ) ;
spaceleft - = strlen ( middle ) ;
2003-05-01 04:29:25 +00:00
}
2006-10-31 11:01:06 +00:00
2008-05-09 19:54:45 +00:00
strncat ( tmp , apex , spaceleft ) ;
time_start = ast_tvnow ( ) ;
ret = ast_search_dns ( context , tmp , C_IN , T_NAPTR , enum_callback ) ;
time_end = ast_tvnow ( ) ;
2011-07-25 19:57:27 +00:00
ast_debug ( 2 , " profiling: %s, %s, % " PRIi64 " ms \n " ,
2008-05-09 19:54:45 +00:00
( ret = = 0 ) ? " OK " : " FAIL " , tmp , ast_tvdiff_ms ( time_end , time_start ) ) ;
2003-09-27 00:22:46 +00:00
if ( ret < 0 ) {
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " No such number found: %s (%s) \n " , tmp , strerror ( errno ) ) ;
2011-08-09 17:08:33 +00:00
context - > naptr_rrs_count = - 1 ;
2006-02-14 22:18:13 +00:00
strcpy ( dst , " 0 " ) ;
2003-04-29 04:26:41 +00:00
ret = 0 ;
}
2005-09-14 01:36:15 +00:00
2007-05-15 23:05:20 +00:00
if ( context - > naptr_rrs_count > = context - > position & & ! ( context - > options & ENUMLOOKUP_OPTIONS_COUNT ) ) {
2006-04-04 19:48:42 +00:00
/* sort array by NAPTR order/preference */
2007-05-15 23:05:20 +00:00
for ( k = 0 ; k < context - > naptr_rrs_count ; k + + ) {
for ( i = 0 ; i < context - > naptr_rrs_count ; i + + ) {
2006-04-04 19:48:42 +00:00
/* use order first and then preference to compare */
2007-05-15 23:05:20 +00:00
if ( ( ntohs ( context - > naptr_rrs [ k ] . naptr . order ) < ntohs ( context - > naptr_rrs [ i ] . naptr . order )
2008-05-09 19:54:45 +00:00
& & context - > naptr_rrs [ k ] . sort_pos > context - > naptr_rrs [ i ] . sort_pos )
| | ( ntohs ( context - > naptr_rrs [ k ] . naptr . order ) > ntohs ( context - > naptr_rrs [ i ] . naptr . order )
& & context - > naptr_rrs [ k ] . sort_pos < context - > naptr_rrs [ i ] . sort_pos ) ) {
2007-05-15 23:05:20 +00:00
z = context - > naptr_rrs [ k ] . sort_pos ;
context - > naptr_rrs [ k ] . sort_pos = context - > naptr_rrs [ i ] . sort_pos ;
context - > naptr_rrs [ i ] . sort_pos = z ;
2006-04-04 19:48:42 +00:00
continue ;
}
2007-05-15 23:05:20 +00:00
if ( ntohs ( context - > naptr_rrs [ k ] . naptr . order ) = = ntohs ( context - > naptr_rrs [ i ] . naptr . order ) ) {
if ( ( ntohs ( context - > naptr_rrs [ k ] . naptr . pref ) < ntohs ( context - > naptr_rrs [ i ] . naptr . pref )
2008-05-09 19:54:45 +00:00
& & context - > naptr_rrs [ k ] . sort_pos > context - > naptr_rrs [ i ] . sort_pos )
| | ( ntohs ( context - > naptr_rrs [ k ] . naptr . pref ) > ntohs ( context - > naptr_rrs [ i ] . naptr . pref )
& & context - > naptr_rrs [ k ] . sort_pos < context - > naptr_rrs [ i ] . sort_pos ) ) {
2007-05-15 23:05:20 +00:00
z = context - > naptr_rrs [ k ] . sort_pos ;
context - > naptr_rrs [ k ] . sort_pos = context - > naptr_rrs [ i ] . sort_pos ;
context - > naptr_rrs [ i ] . sort_pos = z ;
2006-04-04 19:48:42 +00:00
}
}
}
}
2007-05-15 23:05:20 +00:00
for ( k = 0 ; k < context - > naptr_rrs_count ; k + + ) {
2008-03-04 23:04:29 +00:00
if ( context - > naptr_rrs [ k ] . sort_pos = = context - > position - 1 ) {
2007-05-15 23:05:20 +00:00
ast_copy_string ( context - > dst , context - > naptr_rrs [ k ] . result , dstlen ) ;
ast_copy_string ( context - > tech , context - > naptr_rrs [ k ] . tech , techlen ) ;
2006-04-04 19:48:42 +00:00
break ;
}
}
2007-05-15 23:05:20 +00:00
} else if ( ! ( context - > options & ENUMLOOKUP_OPTIONS_COUNT ) ) {
context - > dst [ 0 ] = 0 ;
2008-05-09 19:54:45 +00:00
} else if ( ( context - > options & ENUMLOOKUP_OPTIONS_COUNT ) ) {
2011-08-09 17:08:33 +00:00
snprintf ( context - > dst , context - > dstlen , " %d " , context - > naptr_rrs_count + context - > count ) ;
2006-04-04 19:48:42 +00:00
}
2008-05-09 19:54:45 +00:00
2011-07-25 19:57:27 +00:00
if ( chan ) {
2003-04-29 04:26:41 +00:00
ret | = ast_autoservice_stop ( chan ) ;
2011-07-25 19:57:27 +00:00
}
2005-09-14 01:36:15 +00:00
2007-05-15 23:05:20 +00:00
if ( ! argcontext ) {
for ( k = 0 ; k < context - > naptr_rrs_count ; k + + ) {
2007-06-06 21:20:11 +00:00
ast_free ( context - > naptr_rrs [ k ] . result ) ;
ast_free ( context - > naptr_rrs [ k ] . tech ) ;
2007-05-15 23:05:20 +00:00
}
2007-06-06 21:20:11 +00:00
ast_free ( context - > naptr_rrs ) ;
ast_free ( context ) ;
2011-07-25 19:57:27 +00:00
} else {
2007-05-15 23:05:20 +00:00
* argcontext = context ;
2011-07-25 19:57:27 +00:00
}
2005-09-14 01:36:15 +00:00
2004-05-16 18:12:16 +00:00
return ret ;
}
2008-05-09 19:54:45 +00:00
int ast_get_txt ( struct ast_channel * chan , const char * number , char * txt , int txtlen , char * suffix )
2004-05-16 18:12:16 +00:00
{
2008-05-09 19:54:45 +00:00
struct txt_context context ;
2005-08-11 18:05:25 +00:00
char tmp [ 259 + 512 ] ;
2004-05-16 18:12:16 +00:00
int pos = strlen ( number ) - 1 ;
int newpos = 0 ;
int ret = - 1 ;
2008-05-09 19:54:45 +00:00
ast_debug ( 4 , " ast_get_txt: Number = '%s', suffix = '%s' \n " , number , suffix ) ;
2004-05-16 18:12:16 +00:00
2008-05-09 19:54:45 +00:00
if ( chan & & ast_autoservice_start ( chan ) < 0 ) {
return - 1 ;
}
2012-03-22 19:51:16 +00:00
2008-05-09 19:54:45 +00:00
if ( pos > 128 ) {
2004-05-16 18:12:16 +00:00
pos = 128 ;
}
2005-09-14 01:36:15 +00:00
2008-05-09 19:54:45 +00:00
while ( pos > = 0 ) {
if ( isdigit ( number [ pos ] ) ) {
tmp [ newpos + + ] = number [ pos ] ;
tmp [ newpos + + ] = ' . ' ;
2004-05-16 18:12:16 +00:00
}
2008-05-09 19:54:45 +00:00
pos - - ;
2004-05-16 18:12:16 +00:00
}
2008-05-09 19:54:45 +00:00
ast_copy_string ( & tmp [ newpos ] , suffix , sizeof ( tmp ) - newpos ) ;
2004-05-16 18:12:16 +00:00
if ( ret < 0 ) {
2007-06-14 19:39:12 +00:00
ast_debug ( 2 , " No such number found in ENUM: %s (%s) \n " , tmp , strerror ( errno ) ) ;
2004-05-16 18:12:16 +00:00
ret = 0 ;
2008-05-09 19:54:45 +00:00
} else {
ast_copy_string ( txt , context . txt , txtlen ) ;
2004-05-16 18:12:16 +00:00
}
2008-05-09 19:54:45 +00:00
if ( chan ) {
2004-05-16 18:12:16 +00:00
ret | = ast_autoservice_stop ( chan ) ;
2003-05-01 04:29:25 +00:00
}
2008-05-09 19:54:45 +00:00
return ret ;
2003-05-01 04:29:25 +00:00
}
2006-01-20 00:18:42 +00:00
/*! \brief Initialize the ENUM support subsystem */
2007-08-16 21:09:46 +00:00
static int private_enum_init ( int reload )
2003-05-01 04:29:25 +00:00
{
struct ast_config * cfg ;
2008-05-09 19:54:45 +00:00
const char * string ;
2007-08-16 21:09:46 +00:00
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 } ;
2008-03-26 18:39:06 +00:00
if ( ( cfg = ast_config_load2 ( " enum.conf " , " enum " , config_flags ) ) = = CONFIG_STATUS_FILEUNCHANGED )
2007-08-16 21:09:46 +00:00
return 0 ;
2008-09-12 23:30:03 +00:00
if ( cfg = = CONFIG_STATUS_FILEMISSING | | cfg = = CONFIG_STATUS_FILEUNCHANGED | | cfg = = CONFIG_STATUS_FILEINVALID ) {
return 0 ;
}
2003-05-01 04:29:25 +00:00
/* Destroy existing list */
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & enumlock ) ;
2003-05-01 04:29:25 +00:00
if ( cfg ) {
2008-05-09 19:54:45 +00:00
if ( ( string = ast_variable_retrieve ( cfg , " ienum " , " branchlabel " ) ) ) {
ast_copy_string ( ienum_branchlabel , string , sizeof ( ienum_branchlabel ) ) ;
}
if ( ( string = ast_variable_retrieve ( cfg , " ienum " , " ebl_alg " ) ) ) {
ebl_alg = ENUMLOOKUP_BLR_CC ; /* default */
if ( ! strcasecmp ( string , " txt " ) )
2012-03-22 19:51:16 +00:00
ebl_alg = ENUMLOOKUP_BLR_TXT ;
2008-05-09 19:54:45 +00:00
else if ( ! strcasecmp ( string , " ebl " ) )
2012-03-22 19:51:16 +00:00
ebl_alg = ENUMLOOKUP_BLR_EBL ;
2008-05-09 19:54:45 +00:00
else if ( ! strcasecmp ( string , " cc " ) )
2012-03-22 19:51:16 +00:00
ebl_alg = ENUMLOOKUP_BLR_CC ;
2008-05-09 19:54:45 +00:00
else
ast_log ( LOG_WARNING , " No valid parameter for ienum/ebl_alg. \n " ) ;
2003-05-01 04:29:25 +00:00
}
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2003-05-01 04:29:25 +00:00
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & enumlock ) ;
2003-05-01 04:29:25 +00:00
return 0 ;
}
2007-08-16 21:09:46 +00:00
int ast_enum_init ( void )
{
return private_enum_init ( 0 ) ;
}
2003-05-01 04:29:25 +00:00
int ast_enum_reload ( void )
{
2007-08-16 21:09:46 +00:00
return private_enum_init ( 1 ) ;
2003-05-01 04:29:25 +00:00
}