enum.c: Make ast_get_txt() actually do something.

The ast_get_txt() API function (and by extension, the TXTCIDNAME
dialplan function) were broken in
65b8381550 such that we would never
actually make a DNS TXT query as described.

This patch restores the documented behavior.

ASTERISK-19460 #close
Reported by: George Joseph

Change-Id: I1b19aea711488cb1ecd63843cddce05010e39376
This commit is contained in:
Sean Bright 2020-03-04 17:53:57 -05:00
parent 92b464556f
commit 9a111d188f
1 changed files with 70 additions and 19 deletions

View File

@ -931,37 +931,88 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds
return ret;
}
/*! \internal
* \brief Format a phone number as a domain in an ENUM-adjacent way.
*
* Creates a domain name suitable for query by:
*
* 1. Removing non-digits
* 2. Adding a '.' between adjacent digits
* 3. Reversing the string
* 4. Appending the specified suffix (or e164.arpa if none is specified)
*/
static char *format_numeric_domain(const char *number, const char *suffix)
{
char *buffer, *dst;
size_t suffix_length;
size_t number_length = strlen(number);
const char *src = number + number_length - 1;
if (!suffix) {
suffix = "e164.arpa";
}
suffix_length = strlen(suffix);
dst = buffer = ast_malloc(
(number_length * 2) /* We need 2 bytes per input digit */
+ suffix_length /* ... plus however long the suffix is */
+ 1 /* ... plus room for the '.' separator */
+ 1 /* ... and room for the \0 byte at the end */);
if (buffer) {
while (src >= number) {
if (isdigit(*src)) {
*dst++ = *src;
*dst++ = '.';
}
src--;
}
/* The length arguments below make sure that the \0 byte is copied into
the final string */
if (*suffix == '.') {
memcpy(dst, &suffix[1], suffix_length);
} else {
memcpy(dst, suffix, suffix_length + 1);
}
}
return buffer;
}
int ast_get_txt(struct ast_channel *chan, const char *number, char *txt, int txtlen, char *suffix)
{
struct txt_context context;
char tmp[259 + 512];
int pos = strlen(number) - 1;
int newpos = 0;
int ret = -1;
char *domain;
int ret;
int autoservice = 0;
ast_debug(4, "ast_get_txt: Number = '%s', suffix = '%s'\n", number, suffix);
if (pos > 128) {
pos = 128;
domain = format_numeric_domain(number, suffix);
if (!domain) {
return -1;
}
while (pos >= 0) {
if (isdigit(number[pos])) {
tmp[newpos++] = number[pos];
tmp[newpos++] = '.';
}
pos--;
if (chan) {
/* DNS might take a while, so service the channel while we're blocked */
autoservice = !ast_autoservice_start(chan);
}
ast_copy_string(&tmp[newpos], suffix, sizeof(tmp) - newpos);
if (ret < 0) {
ast_debug(2, "No such number found in ENUM: %s (%s)\n", tmp, strerror(errno));
ret = 0;
} else {
ret = ast_search_dns(&context, domain, C_IN, T_TXT, txt_callback);
if (ret > 0) {
ast_copy_string(txt, context.txt, txtlen);
} else {
ast_debug(2, "No such number found in ENUM: %s (%s)\n", domain, strerror(errno));
}
return ret;
if (autoservice) {
ast_autoservice_stop(chan);
}
ast_free(domain);
return 0;
}
/*! \brief Initialize the ENUM support subsystem */