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 121 if (!number || (strlen(number) < 3)) {
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) {
159 if (answer ==
NULL) {
179 if (i >=
sizeof(c->
txt)) {
181 i =
sizeof(c->
txt) - 1;
201 static int blr_txt(
const char *cc,
const char *suffix)
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);
234 ret = atoi(context.
txt);
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);
267 if (answer ==
NULL) {
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) {
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)) {
365 ast_verb(3,
"blr_txt() BLR EBL record for %s is %d/%s/%s)\n", cc, ret, context.
separator, context.
apex);
371 ast_verb(3,
"blr_txt() BLR EBL record for %s not found (apex: %s)\n", cc, suffix);
376 static 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];
385 ast_log(
LOG_WARNING,
"ENUM parsing failed: Wanted %u characters, got %u\n", len, srclen);
389 if (len > maxdatalen)
391 memcpy(data, src, len);
397 static 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';
423 if (len <
sizeof(
struct naptr)) {
427 answer +=
sizeof(
struct naptr);
428 len -=
sizeof(
struct naptr);
429 if ((res =
parse_ie(flags,
sizeof(flags) - 1, answer, len)) < 0) {
437 if ((res =
parse_ie(services,
sizeof(services) - 1, answer, len)) < 0) {
444 if ((res =
parse_ie(regexp,
sizeof(regexp) - 1, answer, len)) < 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 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);
687 ast_copy_string(naptrinput, number[0] ==
'n' ? number + 1 : number,
sizeof(naptrinput));
688 if (number[0] ==
'+') {
692 if (!(context =
ast_calloc(1,
sizeof(*context)))) {
696 if ((p3 = strchr(naptrinput,
'*'))) {
703 context->
tech = tech;
706 context->
position = record > 0 ? record : 1;
720 if (options !=
NULL) {
721 if (strchr(options,
's')) {
723 }
else if (strchr(options,
'i')) {
725 }
else if (strchr(options,
'd')) {
728 if (strchr(options,
'c')) {
731 if (strchr(number,
'*')) {
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];
779 int cc_len =
cclen(number);
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)) {
813 ast_log(
LOG_WARNING,
"I-ENUM: subdomain location %d behind number %s\n", sdl, 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",
879 (ret == 0) ?
"OK" :
"FAIL", tmp,
ast_tvdiff_ms(time_end, time_start));
882 ast_debug(1,
"No such number found: %s (%s)\n", tmp, strerror(
errno));
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);
975 while (src >= number) {
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",
static int enum_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback from ENUM lookup function.
Main Channel structure associated with a channel.
#define ENUMLOOKUP_OPTIONS_COUNT
Asterisk main include file. File version handling, generic pbx functions.
#define ast_realloc(p, len)
A wrapper for realloc()
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
static char ienum_branchlabel[32]
struct enum_naptr_rr * naptr_rrs
static int private_enum_init(int reload)
Initialize the ENUM support subsystem.
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 cclen(const char *number)
Determine the length of a country code when given an E.164 string.
#define CONFIG_STATUS_FILEINVALID
static ast_mutex_t enumlock
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ast_mutex_lock(a)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
#define ast_strdup(str)
A wrapper for strdup()
#define ENUMLOOKUP_OPTIONS_DIRECT
#define ast_verb(level,...)
#define ast_strlen_zero(foo)
#define ENUMLOOKUP_BLR_CC
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
#define ENUMLOOKUP_BLR_EBL
General Asterisk PBX channel definitions.
static char * format_numeric_domain(const char *number, const char *suffix)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
#define ast_malloc(len)
A wrapper for malloc()
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 answer(void *data)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
#define CONFIG_STATUS_FILEUNCHANGED
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int load_module(void)
static int txt_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback for TXT record lookup, /ol version.
static unsigned int parse_ie(char *data, unsigned int maxdatalen, unsigned char *src, unsigned int srclen)
Parse NAPTR record information elements.
#define ast_calloc(num, len)
A wrapper for calloc()
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 int ebl_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
Callback for EBL record lookup.
Module could not be loaded properly.
Structure used to handle boolean flags.
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 —.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
#define CONFIG_STATUS_FILEMISSING
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int reload_module(void)
#define ENUMLOOKUP_OPTIONS_IENUM
static char context[AST_MAX_CONTEXT]
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define ENUMLOOKUP_OPTIONS_ISN
#define ENUMLOOKUP_BLR_TXT
static int blr_txt(const char *cc, const char *suffix)
Determine the branch location record as stored in a TXT record.
#define AST_MUTEX_DEFINE_STATIC(mutex)
DNS support for Asterisk.
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.
#define ast_mutex_unlock(a)
static int unload_module(void)