63#include <sys/socket.h>
64#include <netinet/in.h>
65#include <arpa/nameser.h>
67#include <arpa/nameser_compat.h>
93#define ENUMLOOKUP_BLR_CC 0
94#define ENUMLOOKUP_BLR_TXT 1
95#define ENUMLOOKUP_BLR_EBL 2
125 strncpy(digits,
number, 2);
127 if (!sscanf(digits,
"%30d", &cc)) {
131 if (cc / 10 == 1 || cc / 10 == 7)
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) {
179 if (i >=
sizeof(
c->txt)) {
181 i =
sizeof(
c->txt) - 1;
201static int blr_txt(
const char *cc,
const char *suffix)
204 char domain[128] =
"";
212 if (
sizeof(domain) < (strlen(cc) * 2 + strlen(
ienum_branchlabel) + strlen(suffix) + 2)) {
221 for (p2 = (
char *) cc + strlen(cc) - 1; p2 >= cc; p2--) {
229 ast_verb(4,
"blr_txt() FQDN for TXT record: %s, cc was %s\n", domain, cc);
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);
242 ast_verb(3,
"blr_txt() BLR TXT record for %s not found (apex: %s)\n", cc, suffix);
290 if ((
c->pos > 15) ||
len < 2) {
308 if ((i = dn_expand((
unsigned char *)fullanswer, (
unsigned char *)
answer +
len,
309 (
unsigned char *)
answer,
c->apex,
sizeof(
c->apex) - 1)) < 0) {
333 char domain[128] =
"";
341 if (
sizeof(domain) < (strlen(cc) * 2 + strlen(
ienum_branchlabel) + strlen(suffix) + 2)) {
350 for (p2 = (
char *) cc + strlen(cc) - 1; p2 >= cc; p2--) {
358 ast_verb(4,
"blr_ebl() FQDN for EBL record: %s, cc was %s\n", domain, cc);
364 if ((ret >= 0) && (ret < 20)) {
371 ast_verb(3,
"blr_txt() BLR EBL record for %s not found (apex: %s)\n", cc, suffix);
376static unsigned int parse_ie(
char *data,
unsigned int maxdatalen,
unsigned char *src,
unsigned int srclen)
378 unsigned int len, olen;
380 len = olen = (
unsigned int) src[0];
389 if (
len > maxdatalen)
391 memcpy(data, src,
len);
397static int parse_naptr(
unsigned char *dst,
int dstsize,
char *tech,
int techsize,
unsigned char *
answer,
int len,
unsigned char *naptrinput)
399 char tech_return[80];
400 char *oanswer = (
char *)
answer;
401 char flags[512] =
"";
402 char services[512] =
"";
404 char regexp[512] =
"";
406 char tempdst[512] =
"";
407 char errbuff[512] =
"";
410 char *pattern, *subst, *
d;
413 static const int max_bt = 10;
414 int size, matchindex;
415 size_t d_len =
sizeof(tempdst) - 1;
417 int re_flags = REG_EXTENDED | REG_NEWLINE;
418 regmatch_t pmatch[max_bt];
420 tech_return[0] =
'\0';
452 if ((res = dn_expand((
unsigned char *)oanswer, (
unsigned char *)
answer +
len, (
unsigned char *)
answer, repl,
sizeof(repl) - 1)) < 0) {
457 ast_debug(3,
"NAPTR input='%s', flags='%s', services='%s', regexp='%s', repl='%s'\n",
458 naptrinput, flags, services, regexp, repl);
461 if (tolower(flags[0]) !=
'u') {
466 p = strstr(services,
"e2u+");
468 p = strstr(services,
"E2U+");
472 p = strchr(p,
':') + 1;
477 p = strstr(services,
"+e2u");
479 p = strstr(services,
"+E2U");
482 p = strchr(services,
':');
489 regexp_len = strlen(regexp);
490 if (regexp_len < 7) {
498 delim2 = strchr(regexp + 1, delim);
500 || ((regexp[regexp_len - 1] !=
'i' || regexp[regexp_len - 2] != delim)
501 && regexp[regexp_len - 1] != delim)) {
504 }
else if (strchr((delim2 + 1), delim) ==
NULL) {
512 if (regexp[regexp_len - 1] ==
'i') {
513 re_flags |= REG_ICASE;
516 pattern = regexp + 1;
519 regexp[regexp_len - 1] = 0;
525 if (regcomp(&preg, pattern, re_flags)) {
537 if ((rc = regexec(&preg, (
char *) naptrinput, max_bt, pmatch, 0))) {
538 regerror(rc, &preg, errbuff,
sizeof(errbuff));
553 while (*subst && (d_len > 0)) {
554 if ((subst[0] ==
'\\') && isdigit(subst[1])) {
555 matchindex = (int) (subst[1] -
'0');
561 size = pmatch[matchindex].rm_eo - pmatch[matchindex].rm_so;
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);
573 ast_log(
LOG_WARNING,
"Error during regex substitution. Invalid backreference index.\n");
576 }
else if (isprint(*subst)) {
586 dst[dstsize - 1] =
'\0';
589 if (!strncasecmp(tech,
"ALL", techsize)){
592 if (!strncasecmp(tech_return, tech,
sizeof(tech_return) < techsize ?
sizeof(tech_return): techsize)){
607#define ENUMLOOKUP_OPTIONS_COUNT 1
609#define ENUMLOOKUP_OPTIONS_ISN 2
611#define ENUMLOOKUP_OPTIONS_IENUM 4
613#define ENUMLOOKUP_OPTIONS_DIRECT 8
630 snprintf(
c->dst,
c->dstlen,
"%d",
c->count);
632 if ((p =
ast_realloc(
c->naptr_rrs,
sizeof(*
c->naptr_rrs) * (
c->naptr_rrs_count + 1)))) {
634 memcpy(&
c->naptr_rrs[
c->naptr_rrs_count].naptr,
answer,
sizeof(
c->naptr_rrs->naptr));
635 c->naptr_rrs[
c->naptr_rrs_count].result =
ast_strdup(
c->dst);
637 c->naptr_rrs[
c->naptr_rrs_count].sort_pos =
c->naptr_rrs_count;
638 c->naptr_rrs_count++;
667 struct timeval time_start, time_end;
674 ast_debug(2,
"num='%s', tech='%s', suffix='%s', options='%s', record=%u\n",
number, tech, suffix,
options, record);
696 if ((p3 = strchr(naptrinput,
'*'))) {
700 context->naptrinput = naptrinput;
706 context->position = record > 0 ? record : 1;
723 }
else if (strchr(
options,
'i')) {
725 }
else if (strchr(
options,
'd')) {
736 ast_debug(1,
"n='%s', tech='%s', suffix='%s', options='%d', record='%d'\n",
767 ast_debug(2,
"ISN ENUM: left=%s, middle='%s'\n", left, middle);
773 ast_debug(2,
"DIRECT ENUM: middle='%s'\n", middle);
778 char sep[256], n_apex[256];
788 sdl =
blr_ebl(cc, suffix, sep,
sizeof(sep) - 1, n_apex,
sizeof(n_apex) - 1);
792 ast_debug(2,
"EBL ENUM: sep=%s, apex='%s'\n", sep, n_apex);
812 if (sdl > strlen(
number)) {
825 if ((sdl * 2 + strlen(middle) + 2) >
sizeof(middle)) {
831 p1 = middle + strlen(middle);
832 for (p2 = (
char *)
number + sdl - 1; p2 >=
number; p2--) {
840 ast_debug(2,
"I-ENUM: cclen=%d, left=%s, middle='%s', apex='%s'\n", cc_len, left, middle, apex);
843 if (strlen(left) * 2 + 2 >
sizeof(domain)) {
851 for (p2 = left + strlen(left); p2 >= left; p2--) {
864 spaceleft =
sizeof(
tmp) - 2;
866 spaceleft -= strlen(domain);
869 strncat(
tmp, middle, spaceleft);
870 spaceleft -= strlen(middle);
873 strncat(
tmp,apex,spaceleft);
878 ast_debug(2,
"profiling: %s, %s, %" PRIi64
" ms\n",
890 for (k = 0; k <
context->naptr_rrs_count; k++) {
891 for (i = 0; i <
context->naptr_rrs_count; i++) {
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;
899 context->naptr_rrs[i].sort_pos = z;
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;
909 context->naptr_rrs[i].sort_pos = z;
914 for (k = 0; k <
context->naptr_rrs_count; k++) {
932 for (k = 0; k <
context->naptr_rrs_count; k++) {
958 size_t suffix_length;
959 size_t number_length = strlen(
number);
960 const char *src =
number + number_length - 1;
963 suffix =
"e164.arpa";
966 suffix_length = strlen(suffix);
985 if (*suffix ==
'.') {
986 memcpy(dst, &suffix[1], suffix_length);
988 memcpy(dst, suffix, suffix_length + 1);
1000 int autoservice = 0;
1002 ast_debug(4,
"ast_get_txt: Number = '%s', suffix = '%s'\n",
number, suffix);
1018 ast_debug(2,
"No such number found in ENUM: %s (%s)\n", domain, strerror(
errno));
1052 if (!strcasecmp(
string,
"txt"))
1054 else if (!strcasecmp(
string,
"ebl"))
1056 else if (!strcasecmp(
string,
"cc"))
1088 .
requires =
"extconfig",
Asterisk main include file. File version handling, generic pbx functions.
#define ast_realloc(p, len)
A wrapper for realloc()
#define ast_strdup(str)
A wrapper for strdup()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
static int answer(void *data)
General Asterisk PBX channel definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
DNS support for Asterisk.
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)
static int private_enum_init(int reload)
Initialize the ENUM support subsystem.
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 —.
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.
static int txt_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback for TXT record lookup, /ol version.
#define ENUMLOOKUP_BLR_TXT
static char ienum_branchlabel[32]
#define ENUMLOOKUP_BLR_CC
static unsigned int parse_ie(char *data, unsigned int maxdatalen, unsigned char *src, unsigned int srclen)
Parse NAPTR record information elements.
static int ebl_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback for EBL record lookup.
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.
static int reload_module(void)
#define ENUMLOOKUP_OPTIONS_COUNT
static char * format_numeric_domain(const char *number, const char *suffix)
#define ENUMLOOKUP_BLR_EBL
static int enum_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback from ENUM lookup function.
static int cclen(const char *number)
Determine the length of a country code when given an E.164 string.
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)
static ast_mutex_t enumlock
#define ENUMLOOKUP_OPTIONS_ISN
static int blr_txt(const char *cc, const char *suffix)
Determine the branch location record as stored in a TXT record.
static int load_module(void)
#define ENUMLOOKUP_OPTIONS_IENUM
static int unload_module(void)
#define ENUMLOOKUP_OPTIONS_DIRECT
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Configuration File Parser.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
@ CONFIG_FLAG_FILEUNCHANGED
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define ast_mutex_unlock(a)
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
@ AST_MODULE_LOAD_SUCCESS
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Main Channel structure associated with a channel.
Structure used to handle boolean flags.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().