Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
Data Structures | Macros | Functions | Variables
enum.c File Reference

ENUM Support for Asterisk. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <ctype.h>
#include <regex.h>
#include "asterisk/module.h"
#include "asterisk/enum.h"
#include "asterisk/dns.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/manager.h"

Go to the source code of this file.

Data Structures

struct  ebl_context
 
struct  txt_context
 

Macros

#define ENUMLOOKUP_BLR_CC   0
 
#define ENUMLOOKUP_BLR_EBL   2
 
#define ENUMLOOKUP_BLR_TXT   1
 
#define ENUMLOOKUP_OPTIONS_COUNT   1
 
#define ENUMLOOKUP_OPTIONS_DIRECT   8
 
#define ENUMLOOKUP_OPTIONS_IENUM   4
 
#define ENUMLOOKUP_OPTIONS_ISN   2
 
#define T_EBL   65300
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
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)
 Lookup entry in ENUM. More...
 
int ast_get_txt (struct ast_channel *chan, const char *number, char *txt, int txtlen, char *suffix)
 Lookup DNS TXT record (used by app TXTCIDnum) More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int blr_ebl (const char *cc, const char *suffix, char *separator, int sep_len, char *apex, int apex_len)
 Evaluate the I-ENUM branch as stored in an EBL record. More...
 
static int blr_txt (const char *cc, const char *suffix)
 Determine the branch location record as stored in a TXT record. More...
 
static int cclen (const char *number)
 Determine the length of a country code when given an E.164 string. More...
 
static int ebl_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer)
 Callback for EBL record lookup. More...
 
static int enum_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer)
 Callback from ENUM lookup function. More...
 
static char * format_numeric_domain (const char *number, const char *suffix)
 
static int load_module (void)
 
static unsigned int parse_ie (char *data, unsigned int maxdatalen, unsigned char *src, unsigned int srclen)
 Parse NAPTR record information elements. More...
 
static int parse_naptr (unsigned char *dst, int dstsize, char *tech, int techsize, unsigned char *answer, int len, unsigned char *naptrinput)
 Parse DNS NAPTR record used in ENUM —. More...
 
static int private_enum_init (int reload)
 Initialize the ENUM support subsystem. More...
 
static int reload_module (void)
 
static int txt_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer)
 Callback for TXT record lookup, /ol version. More...
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "ENUM Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static int ebl_alg = ENUMLOOKUP_BLR_CC
 
static ast_mutex_t enumlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static char ienum_branchlabel [32] = "i"
 

Detailed Description

ENUM Support for Asterisk.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Enum standards
Possible improvement
Todo:

Implement a caching mechanism for multile enum lookups

The service type selection needs to be redone.

Definition in file enum.c.

Macro Definition Documentation

◆ ENUMLOOKUP_BLR_CC

#define ENUMLOOKUP_BLR_CC   0

Definition at line 93 of file enum.c.

Referenced by ast_get_enum(), and private_enum_init().

◆ ENUMLOOKUP_BLR_EBL

#define ENUMLOOKUP_BLR_EBL   2

Definition at line 95 of file enum.c.

Referenced by ast_get_enum(), and private_enum_init().

◆ ENUMLOOKUP_BLR_TXT

#define ENUMLOOKUP_BLR_TXT   1

Definition at line 94 of file enum.c.

Referenced by ast_get_enum(), and private_enum_init().

◆ ENUMLOOKUP_OPTIONS_COUNT

#define ENUMLOOKUP_OPTIONS_COUNT   1

Definition at line 607 of file enum.c.

Referenced by ast_get_enum(), and enum_callback().

◆ ENUMLOOKUP_OPTIONS_DIRECT

#define ENUMLOOKUP_OPTIONS_DIRECT   8

Definition at line 613 of file enum.c.

Referenced by ast_get_enum().

◆ ENUMLOOKUP_OPTIONS_IENUM

#define ENUMLOOKUP_OPTIONS_IENUM   4

Definition at line 611 of file enum.c.

Referenced by ast_get_enum().

◆ ENUMLOOKUP_OPTIONS_ISN

#define ENUMLOOKUP_OPTIONS_ISN   2

Definition at line 609 of file enum.c.

Referenced by ast_get_enum().

◆ T_EBL

#define T_EBL   65300

Definition at line 99 of file enum.c.

Referenced by blr_ebl().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1089 of file enum.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1089 of file enum.c.

◆ ast_get_enum()

int ast_get_enum ( struct ast_channel chan,
const char *  number,
char *  location,
int  maxloc,
char *  technology,
int  maxtech,
char *  suffix,
char *  options,
unsigned int  record,
struct enum_context **  argcontext 
)

Lookup entry in ENUM.

Parameters
chanChannel
numberE164 number with or without the leading +
locationNumber returned (or SIP uri)
maxlocMax length
technologyTechnology (from url scheme in response) You can set it to get particular answer RR, if there are many techs in DNS response, example: "sip" If you need any record, then set it to "ALL" string
maxtechMax length
suffixZone suffix (WARNING: No defaults here any more)
optionsOptions 'c' - Count number of NAPTR RR number - Position of the requested RR in the answer list 'u' - Full URI return (does not strip URI scheme) 'i' - Infrastructure ENUM lookup 's' - ISN based lookup 'd' - Direct DNS query
recordThe position of required RR in the answer list
argcontextArgument for caching results into an enum_context pointer (NULL is used for not caching)
Return values
1if found
0if not found
-1on hangup

Definition at line 649 of file enum.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_search_dns(), ast_strlen_zero, ast_tvdiff_ms(), ast_tvnow(), blr_ebl(), blr_txt(), cclen(), context, enum_context::count, enum_context::dst, enum_context::dstlen, ebl_alg, enum_callback(), enumlock, ENUMLOOKUP_BLR_CC, ENUMLOOKUP_BLR_EBL, ENUMLOOKUP_BLR_TXT, ENUMLOOKUP_OPTIONS_COUNT, ENUMLOOKUP_OPTIONS_DIRECT, ENUMLOOKUP_OPTIONS_IENUM, ENUMLOOKUP_OPTIONS_ISN, errno, ienum_branchlabel, LOG_WARNING, enum_naptr_rr::naptr, enum_context::naptr_rrs, enum_context::naptr_rrs_count, enum_context::naptrinput, NULL, enum_context::options, naptr::order, enum_context::position, naptr::pref, enum_naptr_rr::result, enum_naptr_rr::sort_pos, enum_naptr_rr::tech, enum_context::tech, enum_context::techlen, and tmp().

Referenced by enum_query_read(), and function_enum().

650 {
651  struct enum_context *context;
652  char tmp[512];
653  char domain[256];
654  char left[128];
655  char middle[128];
656  char naptrinput[128];
657  char apex[128] = "";
658  int ret = -1;
659  /* for ISN rewrite */
660  char *p1 = NULL;
661  char *p2 = NULL;
662  char *p3 = NULL;
663  int k = 0;
664  int i = 0;
665  int z = 0;
666  int spaceleft = 0;
667  struct timeval time_start, time_end;
668 
669  if (ast_strlen_zero(suffix)) {
670  ast_log(LOG_WARNING, "ast_get_enum need a suffix parameter now.\n");
671  return -1;
672  }
673 
674  ast_debug(2, "num='%s', tech='%s', suffix='%s', options='%s', record=%u\n", number, tech, suffix, options, record);
675 
676 /*
677  We don't need that any more, that "n" preceding the number has been replaced by a flag
678  in the options paramter.
679  ast_copy_string(naptrinput, number, sizeof(naptrinput));
680 */
681 /*
682  * The "number" parameter includes a leading '+' if it's a full E.164 number (and not ISN)
683  * We need to preserve that as the regex inside NAPTRs expect the +.
684  *
685  * But for the domain generation, the '+' is a nuissance, so we get rid of it.
686 */
687  ast_copy_string(naptrinput, number[0] == 'n' ? number + 1 : number, sizeof(naptrinput));
688  if (number[0] == '+') {
689  number++;
690  }
691 
692  if (!(context = ast_calloc(1, sizeof(*context)))) {
693  return -1;
694  }
695 
696  if ((p3 = strchr(naptrinput, '*'))) {
697  *p3='\0';
698  }
699 
700  context->naptrinput = naptrinput; /* The number */
701  context->dst = dst; /* Return string */
702  context->dstlen = dstlen;
703  context->tech = tech;
704  context->techlen = techlen;
705  context->options = 0;
706  context->position = record > 0 ? record : 1;
707  context->count = 0;
708  context->naptr_rrs = NULL;
709  context->naptr_rrs_count = 0;
710 
711  /*
712  * Process options:
713  *
714  * c Return count, not URI
715  * i Use infrastructure ENUM
716  * s Do ISN transformation
717  * d Direct DNS query: no reversing.
718  *
719  */
720  if (options != NULL) {
721  if (strchr(options,'s')) {
722  context->options |= ENUMLOOKUP_OPTIONS_ISN;
723  } else if (strchr(options,'i')) {
724  context->options |= ENUMLOOKUP_OPTIONS_IENUM;
725  } else if (strchr(options,'d')) {
727  }
728  if (strchr(options,'c')) {
729  context->options |= ENUMLOOKUP_OPTIONS_COUNT;
730  }
731  if (strchr(number,'*')) {
732  context->options |= ENUMLOOKUP_OPTIONS_ISN;
733  }
734  }
735  ast_debug(2, "ENUM options(%s): pos=%d, options='%d'\n", options, context->position, context->options);
736  ast_debug(1, "n='%s', tech='%s', suffix='%s', options='%d', record='%d'\n",
737  number, tech, suffix, context->options, context->position);
738 
739  /*
740  * This code does more than simple RFC3261 ENUM. All these rewriting
741  * schemes have in common that they build the FQDN for the NAPTR lookup
742  * by concatenating
743  * - a number which needs be flipped and "."-seperated (left)
744  * - some fixed string (middle)
745  * - an Apex. (apex)
746  *
747  * The RFC3261 ENUM is: left=full number, middle="", apex=from args.
748  * ISN: number = "middle*left", apex=from args
749  * I-ENUM: EBL parameters build the split, can change apex
750  * Direct: left="", middle=argument, apex=from args
751  *
752  */
753 
754  /* default: the whole number will be flipped, no middle domain component */
755  ast_copy_string(left, number, sizeof(left));
756  middle[0] = '\0';
757  /*
758  * I-ENUM can change the apex, thus we copy it
759  */
760  ast_copy_string(apex, suffix, sizeof(apex));
761  /* ISN rewrite */
762  if ((context->options & ENUMLOOKUP_OPTIONS_ISN) && (p1 = strchr(number, '*'))) {
763  *p1++ = '\0';
764  ast_copy_string(left, number, sizeof(left));
765  ast_copy_string(middle, p1, sizeof(middle) - 1);
766  strcat(middle, ".");
767  ast_debug(2, "ISN ENUM: left=%s, middle='%s'\n", left, middle);
768  /* Direct DNS lookup rewrite */
769  } else if (context->options & ENUMLOOKUP_OPTIONS_DIRECT) {
770  left[0] = 0; /* nothing to flip around */
771  ast_copy_string(middle, number, sizeof(middle) - 1);
772  strcat(middle, ".");
773  ast_debug(2, "DIRECT ENUM: middle='%s'\n", middle);
774  /* Infrastructure ENUM rewrite */
775  } else if (context->options & ENUMLOOKUP_OPTIONS_IENUM) {
776  int sdl = 0;
777  char cc[8];
778  char sep[256], n_apex[256];
779  int cc_len = cclen(number);
780  sdl = cc_len;
782  ast_copy_string(sep, ienum_branchlabel, sizeof(sep)); /* default */
784 
785  switch (ebl_alg) {
786  case ENUMLOOKUP_BLR_EBL:
787  ast_copy_string(cc, number, cc_len); /* cclen() never returns more than 3 */
788  sdl = blr_ebl(cc, suffix, sep, sizeof(sep) - 1, n_apex, sizeof(n_apex) - 1);
789 
790  if (sdl >= 0) {
791  ast_copy_string(apex, n_apex, sizeof(apex));
792  ast_debug(2, "EBL ENUM: sep=%s, apex='%s'\n", sep, n_apex);
793  } else {
794  sdl = cc_len;
795  }
796  break;
797  case ENUMLOOKUP_BLR_TXT:
798  ast_copy_string(cc, number, cc_len); /* cclen() never returns more than 3 */
799  sdl = blr_txt(cc, suffix);
800 
801  if (sdl < 0) {
802  sdl = cc_len;
803  }
804  break;
805 
806  case ENUMLOOKUP_BLR_CC: /* BLR is at the country-code level */
807  default:
808  sdl = cc_len;
809  break;
810  }
811 
812  if (sdl > strlen(number)) { /* Number too short for this sdl? */
813  ast_log(LOG_WARNING, "I-ENUM: subdomain location %d behind number %s\n", sdl, number);
814  ast_free(context);
815  return 0;
816  }
817  ast_copy_string(left, number + sdl, sizeof(left));
818 
820  ast_copy_string(middle, sep, sizeof(middle) - 1);
821  strcat(middle, ".");
823 
824  /* check the space we need for middle */
825  if ((sdl * 2 + strlen(middle) + 2) > sizeof(middle)) {
826  ast_log(LOG_WARNING, "ast_get_enum: not enough space for I-ENUM rewrite.\n");
827  ast_free(context);
828  return -1;
829  }
830 
831  p1 = middle + strlen(middle);
832  for (p2 = (char *) number + sdl - 1; p2 >= number; p2--) {
833  if (isdigit(*p2)) {
834  *p1++ = *p2;
835  *p1++ = '.';
836  }
837  }
838  *p1 = '\0';
839 
840  ast_debug(2, "I-ENUM: cclen=%d, left=%s, middle='%s', apex='%s'\n", cc_len, left, middle, apex);
841  }
842 
843  if (strlen(left) * 2 + 2 > sizeof(domain)) {
844  ast_log(LOG_WARNING, "string to long in ast_get_enum\n");
845  ast_free(context);
846  return -1;
847  }
848 
849  /* flip left into domain */
850  p1 = domain;
851  for (p2 = left + strlen(left); p2 >= left; p2--) {
852  if (isdigit(*p2)) {
853  *p1++ = *p2;
854  *p1++ = '.';
855  }
856  }
857  *p1 = '\0';
858 
859  if (chan && ast_autoservice_start(chan) < 0) {
860  ast_free(context);
861  return -1;
862  }
863 
864  spaceleft = sizeof(tmp) - 2;
865  ast_copy_string(tmp, domain, spaceleft);
866  spaceleft -= strlen(domain);
867 
868  if (*middle) {
869  strncat(tmp, middle, spaceleft);
870  spaceleft -= strlen(middle);
871  }
872 
873  strncat(tmp,apex,spaceleft);
874  time_start = ast_tvnow();
875  ret = ast_search_dns(context, tmp, C_IN, T_NAPTR, enum_callback);
876  time_end = ast_tvnow();
877 
878  ast_debug(2, "profiling: %s, %s, %" PRIi64 " ms\n",
879  (ret == 0) ? "OK" : "FAIL", tmp, ast_tvdiff_ms(time_end, time_start));
880 
881  if (ret < 0) {
882  ast_debug(1, "No such number found: %s (%s)\n", tmp, strerror(errno));
883  context->naptr_rrs_count = -1;
884  strcpy(dst, "0");
885  ret = 0;
886  }
887 
888  if (context->naptr_rrs_count >= context->position && ! (context->options & ENUMLOOKUP_OPTIONS_COUNT)) {
889  /* sort array by NAPTR order/preference */
890  for (k = 0; k < context->naptr_rrs_count; k++) {
891  for (i = 0; i < context->naptr_rrs_count; i++) {
892  /* use order first and then preference to compare */
893  if ((ntohs(context->naptr_rrs[k].naptr.order) < ntohs(context->naptr_rrs[i].naptr.order)
894  && context->naptr_rrs[k].sort_pos > context->naptr_rrs[i].sort_pos)
895  || (ntohs(context->naptr_rrs[k].naptr.order) > ntohs(context->naptr_rrs[i].naptr.order)
896  && context->naptr_rrs[k].sort_pos < context->naptr_rrs[i].sort_pos)) {
897  z = context->naptr_rrs[k].sort_pos;
898  context->naptr_rrs[k].sort_pos = context->naptr_rrs[i].sort_pos;
899  context->naptr_rrs[i].sort_pos = z;
900  continue;
901  }
902  if (ntohs(context->naptr_rrs[k].naptr.order) == ntohs(context->naptr_rrs[i].naptr.order)) {
903  if ((ntohs(context->naptr_rrs[k].naptr.pref) < ntohs(context->naptr_rrs[i].naptr.pref)
904  && context->naptr_rrs[k].sort_pos > context->naptr_rrs[i].sort_pos)
905  || (ntohs(context->naptr_rrs[k].naptr.pref) > ntohs(context->naptr_rrs[i].naptr.pref)
906  && context->naptr_rrs[k].sort_pos < context->naptr_rrs[i].sort_pos)) {
907  z = context->naptr_rrs[k].sort_pos;
908  context->naptr_rrs[k].sort_pos = context->naptr_rrs[i].sort_pos;
909  context->naptr_rrs[i].sort_pos = z;
910  }
911  }
912  }
913  }
914  for (k = 0; k < context->naptr_rrs_count; k++) {
915  if (context->naptr_rrs[k].sort_pos == context->position - 1) {
916  ast_copy_string(context->dst, context->naptr_rrs[k].result, dstlen);
917  ast_copy_string(context->tech, context->naptr_rrs[k].tech, techlen);
918  break;
919  }
920  }
921  } else if (!(context->options & ENUMLOOKUP_OPTIONS_COUNT)) {
922  context->dst[0] = 0;
923  } else if ((context->options & ENUMLOOKUP_OPTIONS_COUNT)) {
924  snprintf(context->dst, context->dstlen, "%d", context->naptr_rrs_count + context->count);
925  }
926 
927  if (chan) {
928  ret |= ast_autoservice_stop(chan);
929  }
930 
931  if (!argcontext) {
932  for (k = 0; k < context->naptr_rrs_count; k++) {
933  ast_free(context->naptr_rrs[k].result);
934  ast_free(context->naptr_rrs[k].tech);
935  }
936  ast_free(context->naptr_rrs);
937  ast_free(context);
938  } else {
939  *argcontext = context;
940  }
941 
942  return ret;
943 }
static int enum_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback from ENUM lookup function.
Definition: enum.c:616
#define ENUMLOOKUP_OPTIONS_COUNT
Definition: enum.c:607
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
int count
Definition: enum.h:49
static char ienum_branchlabel[32]
Definition: enum.c:91
struct enum_naptr_rr * naptr_rrs
Definition: enum.h:51
#define LOG_WARNING
Definition: logger.h:274
int ast_search_dns(void *context, const char *dname, int class, int type, int(*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
Perform DNS lookup (used by DNS, enum and SRV lookups)
Definition: dns.c:493
static int cclen(const char *number)
Determine the length of a country code when given an E.164 string.
Definition: enum.c:116
static ast_mutex_t enumlock
Definition: enum.c:101
static int ebl_alg
Definition: enum.c:96
static int tmp()
Definition: bt_open.c:389
unsigned short pref
Definition: enum.h:30
int dstlen
Definition: enum.h:42
int position
Definition: enum.h:48
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
Domain data structure.
Definition: sip.h:888
#define ENUMLOOKUP_OPTIONS_DIRECT
Definition: enum.c:613
#define ENUMLOOKUP_BLR_CC
Definition: enum.c:93
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define ENUMLOOKUP_BLR_EBL
Definition: enum.c:95
int techlen
Definition: enum.h:44
char * dst
Definition: enum.h:41
unsigned short order
Definition: enum.h:29
struct naptr naptr
Definition: enum.h:34
char * naptrinput
Definition: enum.h:47
char * tech
Definition: enum.h:36
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int errno
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
char * result
Definition: enum.h:35
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
int naptr_rrs_count
Definition: enum.h:52
#define ENUMLOOKUP_OPTIONS_IENUM
Definition: enum.c:611
static struct test_options options
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char * tech
Definition: enum.h:43
int sort_pos
Definition: enum.h:37
#define ENUMLOOKUP_OPTIONS_ISN
Definition: enum.c:609
int options
Definition: enum.h:50
#define ENUMLOOKUP_BLR_TXT
Definition: enum.c:94
static int blr_txt(const char *cc, const char *suffix)
Determine the branch location record as stored in a TXT record.
Definition: enum.c:201
static int blr_ebl(const char *cc, const char *suffix, char *separator, int sep_len, char *apex, int apex_len)
Evaluate the I-ENUM branch as stored in an EBL record.
Definition: enum.c:330
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ ast_get_txt()

int ast_get_txt ( struct ast_channel chan,
const char *  number,
char *  txt,
int  maxtxt,
char *  suffix 
)

Lookup DNS TXT record (used by app TXTCIDnum)

Really has nothing to do with enum, but anyway... Actually, there is now an internet-draft which describes how callerID should be stored in ENUM domains: draft-ietf-enum-cnam-04.txt The algorithm implemented here will thus be obsolete soon.

Parameters
chanChannel
numberE164 number with or without the leading +
txtText string (return value)
maxtxtMax length of "txt"
suffixZone suffix
Version
1.6.1 new suffix parameter to take into account caller ids that aren't in e164.arpa
1.6.1 removed parameters location, maxloc, technology, maxtech as all the information is stored the txt string

Definition at line 995 of file enum.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_debug, ast_free, ast_search_dns(), errno, format_numeric_domain(), txt_context::txt, and txt_callback().

Referenced by function_txtcidname().

996 {
997  struct txt_context context;
998  char *domain;
999  int ret;
1000  int autoservice = 0;
1001 
1002  ast_debug(4, "ast_get_txt: Number = '%s', suffix = '%s'\n", number, suffix);
1003 
1004  domain = format_numeric_domain(number, suffix);
1005  if (!domain) {
1006  return -1;
1007  }
1008 
1009  if (chan) {
1010  /* DNS might take a while, so service the channel while we're blocked */
1011  autoservice = !ast_autoservice_start(chan);
1012  }
1013 
1014  ret = ast_search_dns(&context, domain, C_IN, T_TXT, txt_callback);
1015  if (ret > 0) {
1017  } else {
1018  ast_debug(2, "No such number found in ENUM: %s (%s)\n", domain, strerror(errno));
1019  }
1020 
1021  if (autoservice) {
1022  ast_autoservice_stop(chan);
1023  }
1024 
1025  ast_free(domain);
1026  return 0;
1027 }
char txt[1024]
Definition: enum.c:146
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
int ast_search_dns(void *context, const char *dname, int class, int type, int(*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
Perform DNS lookup (used by DNS, enum and SRV lookups)
Definition: dns.c:493
Domain data structure.
Definition: sip.h:888
int txtlen
Definition: enum.c:147
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static char * format_numeric_domain(const char *number, const char *suffix)
Definition: enum.c:955
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int errno
static int txt_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback for TXT record lookup, /ol version.
Definition: enum.c:151
#define ast_free(a)
Definition: astmm.h:182
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1089 of file enum.c.

◆ blr_ebl()

static int blr_ebl ( const char *  cc,
const char *  suffix,
char *  separator,
int  sep_len,
char *  apex,
int  apex_len 
)
static

Evaluate the I-ENUM branch as stored in an EBL record.

Definition at line 330 of file enum.c.

References ebl_context::apex, ast_copy_string(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_search_dns(), ast_verb, ebl_callback(), enumlock, ienum_branchlabel, LOG_WARNING, ebl_context::pos, ebl_context::separator, and T_EBL.

Referenced by ast_get_enum().

331 {
332  struct ebl_context context;
333  char domain[128] = "";
334  char *p1,*p2;
335  int ret;
336 
338 
339  ast_verb(4, "blr_ebl() cc='%s', suffix='%s', c_bl='%s'\n", cc, suffix, ienum_branchlabel);
340 
341  if (sizeof(domain) < (strlen(cc) * 2 + strlen(ienum_branchlabel) + strlen(suffix) + 2)) {
343  ast_log(LOG_WARNING, "ERROR: string sizing in blr_EBL.\n");
344  return -1;
345  }
346 
347  p1 = domain + snprintf(domain, sizeof(domain), "%s.", ienum_branchlabel);
349 
350  for (p2 = (char *) cc + strlen(cc) - 1; p2 >= cc; p2--) {
351  if (isdigit(*p2)) {
352  *p1++ = *p2;
353  *p1++ = '.';
354  }
355  }
356  strcat(p1, suffix);
357 
358  ast_verb(4, "blr_ebl() FQDN for EBL record: %s, cc was %s\n", domain, cc);
359 
360  ret = ast_search_dns(&context, domain, C_IN, T_EBL, ebl_callback);
361  if (ret > 0) {
362  ret = context.pos;
363 
364  if ((ret >= 0) && (ret < 20)) {
365  ast_verb(3, "blr_txt() BLR EBL record for %s is %d/%s/%s)\n", cc, ret, context.separator, context.apex);
368  return ret;
369  }
370  }
371  ast_verb(3, "blr_txt() BLR EBL record for %s not found (apex: %s)\n", cc, suffix);
372  return -1;
373 }
static char ienum_branchlabel[32]
Definition: enum.c:91
int apex_len
Definition: enum.c:252
#define LOG_WARNING
Definition: logger.h:274
int ast_search_dns(void *context, const char *dname, int class, int type, int(*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
Perform DNS lookup (used by DNS, enum and SRV lookups)
Definition: dns.c:493
static ast_mutex_t enumlock
Definition: enum.c:101
#define ast_mutex_lock(a)
Definition: lock.h:187
Domain data structure.
Definition: sip.h:888
char separator[256]
Definition: enum.c:249
#define ast_verb(level,...)
Definition: logger.h:455
int sep_len
Definition: enum.c:250
char apex[256]
Definition: enum.c:251
#define ast_log
Definition: astobj2.c:42
#define T_EBL
Definition: enum.c:99
static int ebl_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback for EBL record lookup.
Definition: enum.c:256
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ blr_txt()

static int blr_txt ( const char *  cc,
const char *  suffix 
)
static

Determine the branch location record as stored in a TXT record.

Definition at line 201 of file enum.c.

References ast_log, ast_mutex_lock, ast_mutex_unlock, ast_search_dns(), ast_verb, enumlock, ienum_branchlabel, LOG_WARNING, txt_context::txt, and txt_callback().

Referenced by ast_get_enum().

202 {
203  struct txt_context context;
204  char domain[128] = "";
205  char *p1, *p2;
206  int ret;
207 
209 
210  ast_verb(4, "blr_txt() cc='%s', suffix='%s', c_bl='%s'\n", cc, suffix, ienum_branchlabel);
211 
212  if (sizeof(domain) < (strlen(cc) * 2 + strlen(ienum_branchlabel) + strlen(suffix) + 2)) {
214  ast_log(LOG_WARNING, "ERROR: string sizing in blr_txt.\n");
215  return -1;
216  }
217 
218  p1 = domain + snprintf(domain, sizeof(domain), "%s.", ienum_branchlabel);
220 
221  for (p2 = (char *) cc + strlen(cc) - 1; p2 >= cc; p2--) {
222  if (isdigit(*p2)) {
223  *p1++ = *p2;
224  *p1++ = '.';
225  }
226  }
227  strcat(p1, suffix);
228 
229  ast_verb(4, "blr_txt() FQDN for TXT record: %s, cc was %s\n", domain, cc);
230 
231  ret = ast_search_dns(&context, domain, C_IN, T_TXT, txt_callback);
232 
233  if (ret > 0) {
234  ret = atoi(context.txt);
235 
236  if ((ret >= 0) && (ret < 20)) {
237  ast_verb(3, "blr_txt() BLR TXT record for %s is %d (apex: %s)\n", cc, ret, suffix);
238  return ret;
239  }
240  }
241 
242  ast_verb(3, "blr_txt() BLR TXT record for %s not found (apex: %s)\n", cc, suffix);
243 
244  return -1;
245 }
static char ienum_branchlabel[32]
Definition: enum.c:91
#define LOG_WARNING
Definition: logger.h:274
int ast_search_dns(void *context, const char *dname, int class, int type, int(*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
Perform DNS lookup (used by DNS, enum and SRV lookups)
Definition: dns.c:493
static ast_mutex_t enumlock
Definition: enum.c:101
#define ast_mutex_lock(a)
Definition: lock.h:187
Domain data structure.
Definition: sip.h:888
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_log
Definition: astobj2.c:42
static int txt_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback for TXT record lookup, /ol version.
Definition: enum.c:151
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ cclen()

static int cclen ( const char *  number)
static

Determine the length of a country code when given an E.164 string.

Definition at line 116 of file enum.c.

Referenced by ast_get_enum().

117 {
118  int cc;
119  char digits[3] = "";
120 
121  if (!number || (strlen(number) < 3)) {
122  return 0;
123  }
124 
125  strncpy(digits, number, 2);
126 
127  if (!sscanf(digits, "%30d", &cc)) {
128  return 0;
129  }
130 
131  if (cc / 10 == 1 || cc / 10 == 7)
132  return 1;
133 
134  if (cc == 20 || cc == 27 || (cc >= 30 && cc <= 34) || cc == 36 ||
135  cc == 39 || cc == 40 || cc == 41 || (cc >= 40 && cc <= 41) ||
136  (cc >= 43 && cc <= 49) || (cc >= 51 && cc <= 58) ||
137  (cc >= 60 && cc <= 66) || cc == 81 || cc == 82 || cc == 84 ||
138  cc == 86 || (cc >= 90 && cc <= 95) || cc == 98) {
139  return 2;
140  }
141 
142  return 3;
143 }
Number structure.
Definition: app_followme.c:154

◆ ebl_callback()

static int ebl_callback ( void *  context,
unsigned char *  answer,
int  len,
unsigned char *  fullanswer 
)
static

Callback for EBL record lookup.

Definition at line 256 of file enum.c.

References ebl_context::apex, ebl_context::apex_len, ast_copy_string(), ast_log, c, context, LOG_WARNING, NULL, ebl_context::pos, ebl_context::sep_len, and ebl_context::separator.

Referenced by blr_ebl().

257 {
258  struct ebl_context *c = context;
259  int i;
260 
261  c->pos = 0; /* default to empty */
262  c->separator[0] = 0;
263  c->sep_len = 0;
264  c->apex[0] = 0;
265  c->apex_len = 0;
266 
267  if (answer == NULL) {
268  return 0;
269  }
270 
271  /* draft-lendl-enum-branch-location-record-00
272  *
273  * 0 1 2 3 4 5 6 7
274  * +--+--+--+--+--+--+--+--+
275  * | POSITION |
276  * +--+--+--+--+--+--+--+--+
277  * / SEPARATOR /
278  * +--+--+--+--+--+--+--+--+
279  * / APEX /
280  * +--+--+--+--+--+--+--+--+
281  *
282  * where POSITION is a single byte, SEPARATOR is a <character-string>
283  * and APEX is a <domain-name>.
284  *
285  */
286 
287  c->pos = *answer++;
288  len -= 1;
289 
290  if ((c->pos > 15) || len < 2) { /* illegal packet */
291  ast_log(LOG_WARNING, "ebl_callback: malformed EBL record.\n");
292  return 0;
293  }
294 
295  i = *answer++;
296  len -= 1;
297  if (i > len) { /* illegal packet */
298  ast_log(LOG_WARNING, "ebl_callback: malformed EBL record.\n");
299  return 0;
300  }
301 
302  ast_copy_string(c->separator, (char *)answer, i + 1);
303  c->sep_len = i;
304 
305  answer += i;
306  len -= i;
307 
308  if ((i = dn_expand((unsigned char *)fullanswer, (unsigned char *)answer + len,
309  (unsigned char *)answer, c->apex, sizeof(c->apex) - 1)) < 0) {
310  ast_log(LOG_WARNING, "Failed to expand hostname\n");
311  return 0;
312  }
313  c->apex[i] = 0;
314  c->apex_len = i;
315 
316  return 1;
317 }
int apex_len
Definition: enum.c:252
#define LOG_WARNING
Definition: logger.h:274
static struct test_val c
#define NULL
Definition: resample.c:96
char separator[256]
Definition: enum.c:249
unsigned char pos
Definition: enum.c:248
int sep_len
Definition: enum.c:250
char apex[256]
Definition: enum.c:251
#define ast_log
Definition: astobj2.c:42
static int answer(void *data)
Definition: chan_pjsip.c:680
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ enum_callback()

static int enum_callback ( void *  context,
unsigned char *  answer,
int  len,
unsigned char *  fullanswer 
)
static

Callback from ENUM lookup function.

Definition at line 616 of file enum.c.

References ast_log, ast_realloc, ast_strdup, ast_strlen_zero, c, context, enum_context::count, enum_context::dst, enum_context::dstlen, ENUMLOOKUP_OPTIONS_COUNT, LOG_WARNING, enum_naptr_rr::naptr, enum_context::naptr_rrs, enum_context::naptr_rrs_count, enum_context::naptrinput, NULL, enum_context::options, parse_naptr(), enum_naptr_rr::result, enum_naptr_rr::sort_pos, enum_naptr_rr::tech, enum_context::tech, and enum_context::techlen.

Referenced by ast_get_enum().

617 {
618  struct enum_context *c = context;
619  void *p = NULL;
620  int res;
621 
622  res = parse_naptr((unsigned char *)c->dst, c->dstlen, c->tech, c->techlen, answer, len, (unsigned char *)c->naptrinput);
623 
624  if (res < 0) {
625  ast_log(LOG_WARNING, "Failed to parse naptr\n");
626  return -1;
627  } else if ((res == 0) && !ast_strlen_zero(c->dst)) { /* ok, we got needed NAPTR */
628  if (c->options & ENUMLOOKUP_OPTIONS_COUNT) { /* counting RRs */
629  c->count++;
630  snprintf(c->dst, c->dstlen, "%d", c->count);
631  } else {
632  if ((p = ast_realloc(c->naptr_rrs, sizeof(*c->naptr_rrs) * (c->naptr_rrs_count + 1)))) {
633  c->naptr_rrs = p;
634  memcpy(&c->naptr_rrs[c->naptr_rrs_count].naptr, answer, sizeof(c->naptr_rrs->naptr));
638  c->naptr_rrs_count++;
639  }
640  c->dst[0] = 0;
641  }
642  return 0;
643  }
644 
645  return 0;
646 }
#define ENUMLOOKUP_OPTIONS_COUNT
Definition: enum.c:607
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:228
int count
Definition: enum.h:49
struct enum_naptr_rr * naptr_rrs
Definition: enum.h:51
#define LOG_WARNING
Definition: logger.h:274
int dstlen
Definition: enum.h:42
static struct test_val c
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
int techlen
Definition: enum.h:44
char * dst
Definition: enum.h:41
struct naptr naptr
Definition: enum.h:34
char * naptrinput
Definition: enum.h:47
char * tech
Definition: enum.h:36
static int answer(void *data)
Definition: chan_pjsip.c:680
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_strlen_zero(a)
Definition: muted.c:73
static int parse_naptr(unsigned char *dst, int dstsize, char *tech, int techsize, unsigned char *answer, int len, unsigned char *naptrinput)
Parse DNS NAPTR record used in ENUM —.
Definition: enum.c:397
char * result
Definition: enum.h:35
int naptr_rrs_count
Definition: enum.h:52
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char * tech
Definition: enum.h:43
int sort_pos
Definition: enum.h:37
int options
Definition: enum.h:50

◆ format_numeric_domain()

static char* format_numeric_domain ( const char *  number,
const char *  suffix 
)
static

Definition at line 955 of file enum.c.

References ast_malloc.

Referenced by ast_get_txt().

956 {
957  char *buffer, *dst;
958  size_t suffix_length;
959  size_t number_length = strlen(number);
960  const char *src = number + number_length - 1;
961 
962  if (!suffix) {
963  suffix = "e164.arpa";
964  }
965 
966  suffix_length = strlen(suffix);
967 
968  dst = buffer = ast_malloc(
969  (number_length * 2) /* We need 2 bytes per input digit */
970  + suffix_length /* ... plus however long the suffix is */
971  + 1 /* ... plus room for the '.' separator */
972  + 1 /* ... and room for the \0 byte at the end */);
973 
974  if (buffer) {
975  while (src >= number) {
976  if (isdigit(*src)) {
977  *dst++ = *src;
978  *dst++ = '.';
979  }
980  src--;
981  }
982 
983  /* The length arguments below make sure that the \0 byte is copied into
984  the final string */
985  if (*suffix == '.') {
986  memcpy(dst, &suffix[1], suffix_length);
987  } else {
988  memcpy(dst, suffix, suffix_length + 1);
989  }
990  }
991 
992  return buffer;
993 }
Number structure.
Definition: app_followme.c:154
char * dst
Definition: enum.h:41
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193

◆ load_module()

static int load_module ( void  )
static

Definition at line 1067 of file enum.c.

References AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, and private_enum_init().

Referenced by reload_module().

1068 {
1070 }
static int private_enum_init(int reload)
Initialize the ENUM support subsystem.
Definition: enum.c:1030
Module could not be loaded properly.
Definition: module.h:102

◆ parse_ie()

static unsigned int parse_ie ( char *  data,
unsigned int  maxdatalen,
unsigned char *  src,
unsigned int  srclen 
)
static

Parse NAPTR record information elements.

Definition at line 376 of file enum.c.

References ast_log, len(), and LOG_WARNING.

Referenced by parse_naptr().

377 {
378  unsigned int len, olen;
379 
380  len = olen = (unsigned int) src[0];
381  src++;
382  srclen--;
383 
384  if (len > srclen) {
385  ast_log(LOG_WARNING, "ENUM parsing failed: Wanted %u characters, got %u\n", len, srclen);
386  return -1;
387  }
388 
389  if (len > maxdatalen)
390  len = maxdatalen;
391  memcpy(data, src, len);
392 
393  return olen + 1;
394 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ parse_naptr()

static int parse_naptr ( unsigned char *  dst,
int  dstsize,
char *  tech,
int  techsize,
unsigned char *  answer,
int  len,
unsigned char *  naptrinput 
)
static

Parse DNS NAPTR record used in ENUM —.

Definition at line 397 of file enum.c.

References ARRAY_LEN, ast_copy_string(), ast_debug, ast_log, d, LOG_WARNING, NULL, and parse_ie().

Referenced by enum_callback().

398 {
399  char tech_return[80];
400  char *oanswer = (char *)answer;
401  char flags[512] = "";
402  char services[512] = "";
403  char *p;
404  char regexp[512] = "";
405  char repl[512] = "";
406  char tempdst[512] = "";
407  char errbuff[512] = "";
408  char delim;
409  char *delim2;
410  char *pattern, *subst, *d;
411  int res;
412  int regexp_len, rc;
413  static const int max_bt = 10; /* max num of regexp backreference allowed, must remain 10 to guarantee a valid backreference index */
414  int size, matchindex; /* size is the size of the backreference sub. */
415  size_t d_len = sizeof(tempdst) - 1;
416  regex_t preg;
417  int re_flags = REG_EXTENDED | REG_NEWLINE;
418  regmatch_t pmatch[max_bt];
419 
420  tech_return[0] = '\0';
421  dst[0] = '\0';
422 
423  if (len < sizeof(struct naptr)) {
424  ast_log(LOG_WARNING, "NAPTR record length too short\n");
425  return -1;
426  }
427  answer += sizeof(struct naptr);
428  len -= sizeof(struct naptr);
429  if ((res = parse_ie(flags, sizeof(flags) - 1, answer, len)) < 0) {
430  ast_log(LOG_WARNING, "Failed to get flags from NAPTR record\n");
431  return -1;
432  } else {
433  answer += res;
434  len -= res;
435  }
436 
437  if ((res = parse_ie(services, sizeof(services) - 1, answer, len)) < 0) {
438  ast_log(LOG_WARNING, "Failed to get services from NAPTR record\n");
439  return -1;
440  } else {
441  answer += res;
442  len -= res;
443  }
444  if ((res = parse_ie(regexp, sizeof(regexp) - 1, answer, len)) < 0) {
445  ast_log(LOG_WARNING, "Failed to get regexp from NAPTR record\n");
446  return -1;
447  } else {
448  answer += res;
449  len -= res;
450  }
451 
452  if ((res = dn_expand((unsigned char *)oanswer, (unsigned char *)answer + len, (unsigned char *)answer, repl, sizeof(repl) - 1)) < 0) {
453  ast_log(LOG_WARNING, "Failed to expand hostname\n");
454  return -1;
455  }
456 
457  ast_debug(3, "NAPTR input='%s', flags='%s', services='%s', regexp='%s', repl='%s'\n",
458  naptrinput, flags, services, regexp, repl);
459 
460 
461  if (tolower(flags[0]) != 'u') {
462  ast_log(LOG_WARNING, "NAPTR Flag must be 'U' or 'u'.\n");
463  return -1;
464  }
465 
466  p = strstr(services, "e2u+");
467  if (p == NULL)
468  p = strstr(services, "E2U+");
469  if (p){
470  p = p + 4;
471  if (strchr(p, ':')){
472  p = strchr(p, ':') + 1;
473  }
474  ast_copy_string(tech_return, p, sizeof(tech_return));
475  } else {
476 
477  p = strstr(services, "+e2u");
478  if (p == NULL)
479  p = strstr(services, "+E2U");
480  if (p) {
481  *p = 0;
482  p = strchr(services, ':');
483  if (p)
484  *p = 0;
485  ast_copy_string(tech_return, services, sizeof(tech_return));
486  }
487  }
488 
489  regexp_len = strlen(regexp);
490  if (regexp_len < 7) {
491  ast_log(LOG_WARNING, "Regex too short to be meaningful.\n");
492  return -1;
493  }
494 
495  /* this takes the first character of the regexp (which is a delimiter)
496  * and uses that character to find the index of the second delimiter */
497  delim = regexp[0];
498  delim2 = strchr(regexp + 1, delim);
499  if ((delim2 == NULL)
500  || ((regexp[regexp_len - 1] != 'i' || regexp[regexp_len - 2] != delim)
501  && regexp[regexp_len - 1] != delim)) {
502  ast_log(LOG_WARNING, "Regex delimiter error (on \"%s\").\n", regexp);
503  return -1;
504  } 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 */
505  ast_log(LOG_WARNING, "Regex delimiter error (on \"%s\").\n", regexp);
506  return -1;
507  }
508 
509  /* Make the regex case-insensitive if the 'i' flag is present. This assumes you
510  * aren't using 'i' as a delimiter which, altough dubious, does not appear to be
511  * explicitly non-compliant */
512  if (regexp[regexp_len - 1] == 'i') {
513  re_flags |= REG_ICASE;
514  }
515 
516  pattern = regexp + 1; /* pattern is the regex without the begining and ending delimiter */
517  *delim2 = 0; /* zero out the middle delimiter */
518  subst = delim2 + 1; /* dst substring is everything after the second delimiter. */
519  regexp[regexp_len - 1] = 0; /* zero out the last delimiter */
520 
521 /*
522  * now do the regex wizardry.
523  */
524 
525  if (regcomp(&preg, pattern, re_flags)) {
526  ast_log(LOG_WARNING, "NAPTR Regex compilation error (regex = \"%s\").\n", regexp);
527  return -1;
528  }
529 
530  if (preg.re_nsub > ARRAY_LEN(pmatch)) {
531  ast_log(LOG_WARNING, "NAPTR Regex compilation error: too many subs.\n");
532  regfree(&preg);
533  return -1;
534  }
535  /* pmatch is an array containing the substring indexes for the regex backreference sub.
536  * max_bt is the maximum number of backreferences allowed to be stored in pmatch */
537  if ((rc = regexec(&preg, (char *) naptrinput, max_bt, pmatch, 0))) {
538  regerror(rc, &preg, errbuff, sizeof(errbuff));
539  ast_log(LOG_WARNING, "NAPTR Regex match failed. Reason: %s\n", errbuff);
540  regfree(&preg);
541  return -1;
542  }
543  regfree(&preg);
544 
545  d = tempdst;
546  d_len--;
547 
548  /* perform the backreference sub. Search the subst for backreferences,
549  * when a backreference is found, retrieve the backreferences number.
550  * use the backreference number as an index for pmatch to retrieve the
551  * beginning and ending indexes of the substring to insert as the backreference.
552  * if no backreference is found, continue copying the subst into tempdst */
553  while (*subst && (d_len > 0)) {
554  if ((subst[0] == '\\') && isdigit(subst[1])) { /* is this character the beginning of a backreference */
555  matchindex = (int) (subst[1] - '0');
556  if (matchindex >= ARRAY_LEN(pmatch)) {
557  ast_log(LOG_WARNING, "Error during regex substitution. Invalid pmatch index.\n");
558  return -1;
559  }
560  /* pmatch len is 10. we are garanteed a single char 0-9 is a valid index */
561  size = pmatch[matchindex].rm_eo - pmatch[matchindex].rm_so;
562  if (size > d_len) {
563  ast_log(LOG_WARNING, "Not enough space during NAPTR regex substitution.\n");
564  return -1;
565  }
566  /* are the pmatch indexes valid for the input length */
567  if ((strlen((char *) naptrinput) >= pmatch[matchindex].rm_eo) && (pmatch[matchindex].rm_so <= pmatch[matchindex].rm_eo)) {
568  memcpy(d, (naptrinput + (int) pmatch[matchindex].rm_so), size); /* copy input substring into backreference marker */
569  d_len -= size;
570  subst += 2; /* skip over backreference characters to next valid character */
571  d += size;
572  } else {
573  ast_log(LOG_WARNING, "Error during regex substitution. Invalid backreference index.\n");
574  return -1;
575  }
576  } else if (isprint(*subst)) {
577  *d++ = *subst++;
578  d_len--;
579  } else {
580  ast_log(LOG_WARNING, "Error during regex substitution.\n");
581  return -1;
582  }
583  }
584  *d = 0;
585  ast_copy_string((char *) dst, tempdst, dstsize);
586  dst[dstsize - 1] = '\0';
587 
588  if (*tech != '\0'){ /* check if it is requested NAPTR */
589  if (!strncasecmp(tech, "ALL", techsize)){
590  return 0; /* return or count any RR */
591  }
592  if (!strncasecmp(tech_return, tech, sizeof(tech_return) < techsize ? sizeof(tech_return): techsize)){
593  ast_copy_string(tech, tech_return, techsize);
594  return 0; /* we got our RR */
595  } else { /* go to the next RR in the DNS answer */
596  return 1;
597  }
598  }
599 
600  /* tech was not specified, return first parsed RR */
601  ast_copy_string(tech, tech_return, techsize);
602 
603  return 0;
604 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define LOG_WARNING
Definition: logger.h:274
static struct test_val d
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
char * dst
Definition: enum.h:41
static int answer(void *data)
Definition: chan_pjsip.c:680
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static unsigned int parse_ie(char *data, unsigned int maxdatalen, unsigned char *src, unsigned int srclen)
Parse NAPTR record information elements.
Definition: enum.c:376
Definition: enum.h:28
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ private_enum_init()

static int private_enum_init ( int  reload)
static

Initialize the ENUM support subsystem.

Definition at line 1030 of file enum.c.

References ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, ebl_alg, enumlock, ENUMLOOKUP_BLR_CC, ENUMLOOKUP_BLR_EBL, ENUMLOOKUP_BLR_TXT, ienum_branchlabel, LOG_WARNING, and string.

Referenced by load_module(), and reload_module().

1031 {
1032  struct ast_config *cfg;
1033  const char *string;
1034  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1035 
1036  if ((cfg = ast_config_load2("enum.conf", "enum", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
1037  return 0;
1039  return 0;
1040  }
1041 
1042  /* Destroy existing list */
1044  if (cfg) {
1045  if ((string = ast_variable_retrieve(cfg, "ienum", "branchlabel"))) {
1047  }
1048 
1049  if ((string = ast_variable_retrieve(cfg, "ienum", "ebl_alg"))) {
1050  ebl_alg = ENUMLOOKUP_BLR_CC; /* default */
1051 
1052  if (!strcasecmp(string, "txt"))
1054  else if (!strcasecmp(string, "ebl"))
1056  else if (!strcasecmp(string, "cc"))
1058  else
1059  ast_log(LOG_WARNING, "No valid parameter for ienum/ebl_alg.\n");
1060  }
1061  ast_config_destroy(cfg);
1062  }
1064  return 0;
1065 }
static char ienum_branchlabel[32]
Definition: enum.c:91
#define LOG_WARNING
Definition: logger.h:274
static ast_mutex_t enumlock
Definition: enum.c:101
#define CONFIG_STATUS_FILEINVALID
static int ebl_alg
Definition: enum.c:96
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3154
const char * string
Definition: presencestate.c:71
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ENUMLOOKUP_BLR_CC
Definition: enum.c:93
#define ast_log
Definition: astobj2.c:42
#define ENUMLOOKUP_BLR_EBL
Definition: enum.c:95
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define CONFIG_STATUS_FILEUNCHANGED
static int reload(void)
Definition: cdr_mysql.c:741
Structure used to handle boolean flags.
Definition: utils.h:199
#define CONFIG_STATUS_FILEMISSING
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define ENUMLOOKUP_BLR_TXT
Definition: enum.c:94
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 1077 of file enum.c.

References AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CORE, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, load_module(), private_enum_init(), reload(), and unload_module().

1078 {
1079  return private_enum_init(1);
1080 }
static int private_enum_init(int reload)
Initialize the ENUM support subsystem.
Definition: enum.c:1030

◆ txt_callback()

static int txt_callback ( void *  context,
unsigned char *  answer,
int  len,
unsigned char *  fullanswer 
)
static

Callback for TXT record lookup, /ol version.

Definition at line 151 of file enum.c.

References ast_copy_string(), ast_log, c, context, LOG_WARNING, NULL, txt_context::txt, and txt_context::txtlen.

Referenced by ast_get_txt(), and blr_txt().

152 {
153  struct txt_context *c = context;
154  unsigned int i;
155 
156  c->txt[0] = 0; /* default to empty */
157  c->txtlen = 0;
158 
159  if (answer == NULL) {
160  return 0;
161  }
162 
163  /* RFC1035:
164  *
165  * <character-string> is a single length octet followed by that number of characters.
166  * TXT-DATA One or more <character-string>s.
167  *
168  * We only take the first string here.
169  */
170 
171  i = *answer++;
172  len -= 1;
173 
174  if (i > len) { /* illegal packet */
175  ast_log(LOG_WARNING, "txt_callback: malformed TXT record.\n");
176  return 0;
177  }
178 
179  if (i >= sizeof(c->txt)) { /* too long? */
180  ast_log(LOG_WARNING, "txt_callback: TXT record too long.\n");
181  i = sizeof(c->txt) - 1;
182  }
183 
184  ast_copy_string(c->txt, (char *)answer, i + 1); /* this handles the \0 termination */
185  c->txtlen = i;
186 
187  return 1;
188 }
char txt[1024]
Definition: enum.c:146
#define LOG_WARNING
Definition: logger.h:274
static struct test_val c
#define NULL
Definition: resample.c:96
int txtlen
Definition: enum.c:147
#define ast_log
Definition: astobj2.c:42
static int answer(void *data)
Definition: chan_pjsip.c:680
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1072 of file enum.c.

Referenced by reload_module().

1073 {
1074  return 0;
1075 }

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "ENUM Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
static

Definition at line 1089 of file enum.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1089 of file enum.c.

◆ ebl_alg

int ebl_alg = ENUMLOOKUP_BLR_CC
static

Definition at line 96 of file enum.c.

Referenced by ast_get_enum(), and private_enum_init().

◆ enumlock

ast_mutex_t enumlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 101 of file enum.c.

Referenced by ast_get_enum(), blr_ebl(), blr_txt(), and private_enum_init().

◆ ienum_branchlabel

char ienum_branchlabel[32] = "i"
static

Definition at line 91 of file enum.c.

Referenced by ast_get_enum(), blr_ebl(), blr_txt(), and private_enum_init().