mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 12:16:00 +00:00
Fix ENUM documentation (bug #3698)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5115 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
6
dns.c
6
dns.c
@@ -89,6 +89,7 @@ static int skip_name(u_char *s, int len)
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--- dns_parse_answer: Parse DNS lookup result, call callback */
|
||||||
static int dns_parse_answer(void *context,
|
static int dns_parse_answer(void *context,
|
||||||
int class, int type, u_char *answer, int len,
|
int class, int type, u_char *answer, int len,
|
||||||
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
|
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
|
||||||
@@ -160,6 +161,7 @@ AST_MUTEX_DEFINE_STATIC(res_lock);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*--- ast_search_dns: Lookup record in DNS */
|
||||||
int ast_search_dns(void *context,
|
int ast_search_dns(void *context,
|
||||||
const char *dname, int class, int type,
|
const char *dname, int class, int type,
|
||||||
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
|
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
|
||||||
@@ -180,11 +182,11 @@ int ast_search_dns(void *context,
|
|||||||
#endif
|
#endif
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
|
if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
|
||||||
ast_log(LOG_WARNING, "Parse error\n");
|
ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
else if (ret == 0) {
|
else if (ret == 0) {
|
||||||
ast_log(LOG_DEBUG, "No matches found\n");
|
ast_log(LOG_DEBUG, "No matches found in DNS for %s\n", dname);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
89
enum.c
89
enum.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* ENUM Support for Asterisk
|
* ENUM Support for Asterisk
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003 Digium
|
* Copyright (C) 2003-2005, Digium, inc
|
||||||
*
|
*
|
||||||
* Written by Mark Spencer <markster@digium.com>
|
* Written by Mark Spencer <markster@digium.com>
|
||||||
*
|
*
|
||||||
@@ -44,8 +44,10 @@
|
|||||||
#define T_TXT 16
|
#define T_TXT 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* The IETF Enum standard root, managed by the ITU */
|
||||||
#define TOPLEV "e164.arpa."
|
#define TOPLEV "e164.arpa."
|
||||||
|
|
||||||
|
/* Linked list from config file */
|
||||||
static struct enum_search {
|
static struct enum_search {
|
||||||
char toplev[80];
|
char toplev[80];
|
||||||
struct enum_search *next;
|
struct enum_search *next;
|
||||||
@@ -60,9 +62,11 @@ struct naptr {
|
|||||||
unsigned short pref;
|
unsigned short pref;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
/*--- parse_ie: Parse NAPTR record information elements */
|
||||||
static int parse_ie(unsigned char *data, int maxdatalen, unsigned char *src, int srclen)
|
static int parse_ie(unsigned char *data, int maxdatalen, unsigned char *src, int srclen)
|
||||||
{
|
{
|
||||||
int len, olen;
|
int len, olen;
|
||||||
|
|
||||||
len = olen = (int)src[0];
|
len = olen = (int)src[0];
|
||||||
src++;
|
src++;
|
||||||
srclen--;
|
srclen--;
|
||||||
@@ -76,6 +80,7 @@ static int parse_ie(unsigned char *data, int maxdatalen, unsigned char *src, int
|
|||||||
return olen + 1;
|
return olen + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--- parse_naptr: Parse DNS NAPTR record used in ENUM ---*/
|
||||||
static int parse_naptr(unsigned char *dst, int dstsize, char *tech, int techsize, unsigned char *answer, int len, char *naptrinput)
|
static int parse_naptr(unsigned char *dst, int dstsize, char *tech, int techsize, unsigned char *answer, int len, char *naptrinput)
|
||||||
{
|
{
|
||||||
unsigned char *oanswer = answer;
|
unsigned char *oanswer = answer;
|
||||||
@@ -97,31 +102,43 @@ static int parse_naptr(unsigned char *dst, int dstsize, char *tech, int techsize
|
|||||||
dst[0] = '\0';
|
dst[0] = '\0';
|
||||||
|
|
||||||
if (len < sizeof(struct naptr)) {
|
if (len < sizeof(struct naptr)) {
|
||||||
ast_log(LOG_WARNING, "Length too short\n");
|
ast_log(LOG_WARNING, "NAPTR record length too short\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
answer += sizeof(struct naptr);
|
answer += sizeof(struct naptr);
|
||||||
len -= sizeof(struct naptr);
|
len -= sizeof(struct naptr);
|
||||||
if ((res = parse_ie(flags, sizeof(flags) - 1, answer, len)) < 0) {
|
if ((res = parse_ie(flags, sizeof(flags) - 1, answer, len)) < 0) {
|
||||||
ast_log(LOG_WARNING, "Failed to get flags\n");
|
ast_log(LOG_WARNING, "Failed to get flags from NAPTR record\n");
|
||||||
return -1;
|
return -1;
|
||||||
} else { answer += res; len -= res; }
|
} else {
|
||||||
|
answer += res;
|
||||||
|
len -= res;
|
||||||
|
}
|
||||||
if ((res = parse_ie(services, sizeof(services) - 1, answer, len)) < 0) {
|
if ((res = parse_ie(services, sizeof(services) - 1, answer, len)) < 0) {
|
||||||
ast_log(LOG_WARNING, "Failed to get services\n");
|
ast_log(LOG_WARNING, "Failed to get services from NAPTR record\n");
|
||||||
return -1;
|
return -1;
|
||||||
} else { answer += res; len -= res; }
|
} else {
|
||||||
if ((res = parse_ie(regexp, sizeof(regexp) - 1, answer, len)) < 0)
|
answer += res;
|
||||||
return -1; else { answer += res; len -= res; }
|
len -= res;
|
||||||
|
}
|
||||||
|
if ((res = parse_ie(regexp, sizeof(regexp) - 1, answer, len)) < 0) {
|
||||||
|
ast_log(LOG_WARNING, "Failed to get regexp from NAPTR record\n");
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
answer += res;
|
||||||
|
len -= res;
|
||||||
|
}
|
||||||
if ((res = dn_expand(oanswer,answer + len,answer, repl, sizeof(repl) - 1)) < 0) {
|
if ((res = dn_expand(oanswer,answer + len,answer, repl, sizeof(repl) - 1)) < 0) {
|
||||||
ast_log(LOG_WARNING, "Failed to expand hostname\n");
|
ast_log(LOG_WARNING, "Failed to expand hostname\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_log(LOG_DEBUG, "input='%s', flags='%s', services='%s', regexp='%s', repl='%s'\n",
|
if (option_debug > 2) /* Advanced NAPTR debugging */
|
||||||
|
ast_log(LOG_DEBUG, "NAPTR input='%s', flags='%s', services='%s', regexp='%s', repl='%s'\n",
|
||||||
naptrinput, flags, services, regexp, repl);
|
naptrinput, flags, services, regexp, repl);
|
||||||
|
|
||||||
if (tolower(flags[0]) != 'u') {
|
if (tolower(flags[0]) != 'u') {
|
||||||
ast_log(LOG_WARNING, "Flag must be 'U' or 'u'.\n");
|
ast_log(LOG_WARNING, "NAPTR Flag must be 'U' or 'u'.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,30 +200,31 @@ static int parse_naptr(unsigned char *dst, int dstsize, char *tech, int techsize
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (regcomp(&preg, pattern, REG_EXTENDED | REG_NEWLINE)) {
|
if (regcomp(&preg, pattern, REG_EXTENDED | REG_NEWLINE)) {
|
||||||
ast_log(LOG_WARNING, "Regex compilation error (regex = \"%s\").\n",regexp);
|
ast_log(LOG_WARNING, "NAPTR Regex compilation error (regex = \"%s\").\n",regexp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg.re_nsub > 9) {
|
if (preg.re_nsub > 9) {
|
||||||
ast_log(LOG_WARNING, "Regex compilation error: too many subs.\n");
|
ast_log(LOG_WARNING, "NAPTR Regex compilation error: too many subs.\n");
|
||||||
regfree(&preg);
|
regfree(&preg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regexec(&preg, naptrinput, 9, pmatch, 0)) {
|
if (regexec(&preg, naptrinput, 9, pmatch, 0)) {
|
||||||
ast_log(LOG_WARNING, "Regex match failed.\n");
|
ast_log(LOG_WARNING, "NAPTR Regex match failed.\n");
|
||||||
regfree(&preg);
|
regfree(&preg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
regfree(&preg);
|
regfree(&preg);
|
||||||
|
|
||||||
d = temp; d_len--;
|
d = temp;
|
||||||
|
d_len--;
|
||||||
while( *subst && (d_len > 0) ) {
|
while( *subst && (d_len > 0) ) {
|
||||||
if ((subst[0] == '\\') && isdigit(subst[1]) && (pmatch[subst[1]-'0'].rm_so != -1)) {
|
if ((subst[0] == '\\') && isdigit(subst[1]) && (pmatch[subst[1]-'0'].rm_so != -1)) {
|
||||||
backref = subst[1]-'0';
|
backref = subst[1]-'0';
|
||||||
size = pmatch[backref].rm_eo - pmatch[backref].rm_so;
|
size = pmatch[backref].rm_eo - pmatch[backref].rm_so;
|
||||||
if (size > d_len) {
|
if (size > d_len) {
|
||||||
ast_log(LOG_WARNING, "Not enough space during regex substitution.\n");
|
ast_log(LOG_WARNING, "Not enough space during NAPTR regex substitution.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(d, naptrinput + pmatch[backref].rm_so, size);
|
memcpy(d, naptrinput + pmatch[backref].rm_so, size);
|
||||||
@@ -228,15 +246,16 @@ static int parse_naptr(unsigned char *dst, int dstsize, char *tech, int techsize
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct enum_context {
|
struct enum_context {
|
||||||
char *dst;
|
char *dst; /* Destination part of URL from ENUM */
|
||||||
int dstlen;
|
int dstlen; /* Length */
|
||||||
char *tech;
|
char *tech; /* Technology (from URL scheme) */
|
||||||
int techlen;
|
int techlen; /* Length */
|
||||||
char *txt;
|
char *txt; /* TXT record in TXT lookup */
|
||||||
int txtlen;
|
int txtlen; /* Length */
|
||||||
char *naptrinput;
|
char *naptrinput; /* The number to lookup */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*--- txt_callback: Callback for TXT record lookup */
|
||||||
static int txt_callback(void *context, u_char *answer, int len, u_char *fullanswer)
|
static int txt_callback(void *context, u_char *answer, int len, u_char *fullanswer)
|
||||||
{
|
{
|
||||||
struct enum_context *c = (struct enum_context *)context;
|
struct enum_context *c = (struct enum_context *)context;
|
||||||
@@ -244,18 +263,18 @@ static int txt_callback(void *context, u_char *answer, int len, u_char *fullansw
|
|||||||
printf("ENUMTXT Called\n");
|
printf("ENUMTXT Called\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (answer != NULL) {
|
if (answer == NULL) {
|
||||||
c->txtlen = strlen(answer);
|
|
||||||
strncpy(c->txt, answer, sizeof(c->txt) - 1);
|
|
||||||
c->txt[sizeof(c->txt) - 1] = 0;
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
c->txt = NULL;
|
c->txt = NULL;
|
||||||
c->txtlen = 0;
|
c->txtlen = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
strncpy(c->txt, answer, sizeof(c->txt) - 1);
|
||||||
|
c->txt[sizeof(c->txt) - 1] = 0; /* Make sure the string is terminated */
|
||||||
|
c->txtlen = strlen(c->txt);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--- enum_callback: Callback from ENUM lookup function */
|
||||||
static int enum_callback(void *context, u_char *answer, int len, u_char *fullanswer)
|
static int enum_callback(void *context, u_char *answer, int len, u_char *fullanswer)
|
||||||
{
|
{
|
||||||
struct enum_context *c = (struct enum_context *)context;
|
struct enum_context *c = (struct enum_context *)context;
|
||||||
@@ -271,6 +290,7 @@ static int enum_callback(void *context, u_char *answer, int len, u_char *fullans
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--- ast_get_enum: ENUM lookup */
|
||||||
int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen)
|
int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen)
|
||||||
{
|
{
|
||||||
struct enum_context context;
|
struct enum_context context;
|
||||||
@@ -284,10 +304,10 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds
|
|||||||
|
|
||||||
strncat(naptrinput, number, sizeof(naptrinput) - 2);
|
strncat(naptrinput, number, sizeof(naptrinput) - 2);
|
||||||
|
|
||||||
context.naptrinput = naptrinput;
|
context.naptrinput = naptrinput; /* The number */
|
||||||
context.dst = dst;
|
context.dst = dst; /* Return string */
|
||||||
context.dstlen = dstlen;
|
context.dstlen = dstlen;
|
||||||
context.tech = tech;
|
context.tech = tech; /* Return string */
|
||||||
context.techlen = techlen;
|
context.techlen = techlen;
|
||||||
|
|
||||||
if (pos > 128)
|
if (pos > 128)
|
||||||
@@ -328,6 +348,9 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--- ast_get_txt: Get TXT record from DNS.
|
||||||
|
Really has nothing to do with enum, but anyway...
|
||||||
|
*/
|
||||||
int ast_get_txt(struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen, char *txt, int txtlen)
|
int ast_get_txt(struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen, char *txt, int txtlen)
|
||||||
{
|
{
|
||||||
struct enum_context context;
|
struct enum_context context;
|
||||||
@@ -374,6 +397,7 @@ int ast_get_txt(struct ast_channel *chan, const char *number, char *dst, int dst
|
|||||||
ast_mutex_unlock(&enumlock);
|
ast_mutex_unlock(&enumlock);
|
||||||
if (!s)
|
if (!s)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = ast_search_dns(&context, tmp, C_IN, T_TXT, txt_callback);
|
ret = ast_search_dns(&context, tmp, C_IN, T_TXT, txt_callback);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
break;
|
break;
|
||||||
@@ -387,9 +411,11 @@ int ast_get_txt(struct ast_channel *chan, const char *number, char *dst, int dst
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--- enum_newtoplev: Add enum tree to linked list ---*/
|
||||||
static struct enum_search *enum_newtoplev(char *s)
|
static struct enum_search *enum_newtoplev(char *s)
|
||||||
{
|
{
|
||||||
struct enum_search *tmp;
|
struct enum_search *tmp;
|
||||||
|
|
||||||
tmp = malloc(sizeof(struct enum_search));
|
tmp = malloc(sizeof(struct enum_search));
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
memset(tmp, 0, sizeof(struct enum_search));
|
memset(tmp, 0, sizeof(struct enum_search));
|
||||||
@@ -398,6 +424,7 @@ static struct enum_search *enum_newtoplev(char *s)
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--- ast_enum_init: Initialize the ENUM support subsystem */
|
||||||
int ast_enum_init(void)
|
int ast_enum_init(void)
|
||||||
{
|
{
|
||||||
struct ast_config *cfg;
|
struct ast_config *cfg;
|
||||||
|
@@ -14,6 +14,13 @@
|
|||||||
|
|
||||||
struct ast_channel;
|
struct ast_channel;
|
||||||
|
|
||||||
|
/*! \brief Perform DNS lookup (used by enum and SRV lookups)
|
||||||
|
\param context
|
||||||
|
\param dname Domain name to lookup (host, SRV domain, TXT record name)
|
||||||
|
\param class Record Class (see "man res_search")
|
||||||
|
\param type Record type (see "man res_search")
|
||||||
|
\param callback Callback function for handling DNS result
|
||||||
|
*/
|
||||||
extern int ast_search_dns(void *context, const char *dname, int class, int type,
|
extern int ast_search_dns(void *context, const char *dname, int class, int type,
|
||||||
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer));
|
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer));
|
||||||
|
|
||||||
|
@@ -3,19 +3,42 @@
|
|||||||
*
|
*
|
||||||
* ENUM support
|
* ENUM support
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999, Mark Spencer
|
* Copyright (C) 1999-2005, Digium, inc
|
||||||
*
|
*
|
||||||
* Mark Spencer <markster@linux-support.net>
|
* Mark Spencer <markster@digium.com>
|
||||||
*
|
*
|
||||||
* This program is free software, distributed under the terms of
|
* This program is free software, distributed under the terms of
|
||||||
* the GNU General Public License
|
* the GNU General Public License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*! \file enum.h
|
||||||
|
\brief DNS and ENUM functions
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _ASTERISK_ENUM_H
|
#ifndef _ASTERISK_ENUM_H
|
||||||
#define _ASTERISK_ENUM_H
|
#define _ASTERISK_ENUM_H
|
||||||
#include <asterisk/channel.h>
|
#include <asterisk/channel.h>
|
||||||
/* Lookup entry in ENUM Returns 1 if found, 0 if not found, -1 on hangup */
|
/*! \brief Lookup entry in ENUM Returns 1 if found, 0 if not found, -1 on hangup
|
||||||
|
\param chan Channel
|
||||||
|
\param number Number in E164 format without the + (for e164.arpa) or format
|
||||||
|
requested by enum service used (enum.conf)
|
||||||
|
\param location Number returned (or SIP uri)
|
||||||
|
\param maxloc Max length
|
||||||
|
\param tech Technology (from url scheme in response)
|
||||||
|
\param maxtech Max length
|
||||||
|
*/
|
||||||
extern int ast_get_enum(struct ast_channel *chan, const char *number, char *location, int maxloc, char *technology, int maxtech);
|
extern int ast_get_enum(struct ast_channel *chan, const char *number, char *location, int maxloc, char *technology, int maxtech);
|
||||||
|
|
||||||
|
/*! \brief Lookup DNS TXT record (used by app TXTCIDnum
|
||||||
|
\param chan Channel
|
||||||
|
\param number E164 number without the +
|
||||||
|
\param locatio Number returned (or SIP uri)
|
||||||
|
\param maxloc Max length of number
|
||||||
|
\param tech Technology (not used in TXT records)
|
||||||
|
\param maxtech Max length
|
||||||
|
\param txt Text string (return value)
|
||||||
|
\param maxtxt Max length of "txt"
|
||||||
|
*/
|
||||||
extern int ast_get_txt(struct ast_channel *chan, const char *number, char *location, int maxloc, char *technology, int maxtech, char *txt, int maxtxt);
|
extern int ast_get_txt(struct ast_channel *chan, const char *number, char *location, int maxloc, char *technology, int maxtech, char *txt, int maxtxt);
|
||||||
|
|
||||||
extern int ast_enum_init(void);
|
extern int ast_enum_init(void);
|
||||||
|
Reference in New Issue
Block a user