Skip to content
Snippets Groups Projects
Commit a5a45131 authored by Mark Spencer's avatar Mark Spencer
Browse files

Fix ENUM documentation (bug #3698)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5115 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent 0eab1fab
No related branches found
No related tags found
No related merge requests found
......@@ -89,9 +89,10 @@ static int skip_name(u_char *s, int len)
return x;
}
/*--- dns_parse_answer: Parse DNS lookup result, call callback */
static int dns_parse_answer(void *context,
int class, int type, u_char *answer, int len,
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
int class, int type, u_char *answer, int len,
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
{
u_char *fullanswer = answer;
struct dn_answer *ans;
......@@ -160,9 +161,10 @@ AST_MUTEX_DEFINE_STATIC(res_lock);
#endif
#endif
/*--- ast_search_dns: Lookup record in DNS */
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))
const char *dname, int class, int type,
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
{
#ifdef HAS_RES_NINIT
struct __res_state dnsstate;
......@@ -180,11 +182,11 @@ int ast_search_dns(void *context,
#endif
if (res > 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;
}
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;
}
else
......
/*
* ENUM Support for Asterisk
*
* Copyright (C) 2003 Digium
* Copyright (C) 2003-2005, Digium, inc
*
* Written by Mark Spencer <markster@digium.com>
*
......@@ -44,8 +44,10 @@
#define T_TXT 16
#endif
/* The IETF Enum standard root, managed by the ITU */
#define TOPLEV "e164.arpa."
/* Linked list from config file */
static struct enum_search {
char toplev[80];
struct enum_search *next;
......@@ -60,9 +62,11 @@ struct naptr {
unsigned short pref;
} __attribute__ ((__packed__));
/*--- parse_ie: Parse NAPTR record information elements */
static int parse_ie(unsigned char *data, int maxdatalen, unsigned char *src, int srclen)
{
int len, olen;
len = olen = (int)src[0];
src++;
srclen--;
......@@ -76,6 +80,7 @@ static int parse_ie(unsigned char *data, int maxdatalen, unsigned char *src, int
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)
{
unsigned char *oanswer = answer;
......@@ -97,31 +102,43 @@ static int parse_naptr(unsigned char *dst, int dstsize, char *tech, int techsize
dst[0] = '\0';
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;
}
answer += sizeof(struct naptr);
len -= sizeof(struct naptr);
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;
} else { answer += res; len -= res; }
} else {
answer += res;
len -= res;
}
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;
} else {
answer += 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 = parse_ie(regexp, sizeof(regexp) - 1, answer, len)) < 0)
return -1; else { answer += res; len -= res; }
} else {
answer += res;
len -= res;
}
if ((res = dn_expand(oanswer,answer + len,answer, repl, sizeof(repl) - 1)) < 0) {
ast_log(LOG_WARNING, "Failed to expand hostname\n");
return -1;
}
ast_log(LOG_DEBUG, "input='%s', flags='%s', services='%s', regexp='%s', repl='%s'\n",
naptrinput, flags, services, regexp, repl);
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);
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;
}
......@@ -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)) {
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;
}
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);
return -1;
}
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);
return -1;
}
regfree(&preg);
d = temp; d_len--;
d = temp;
d_len--;
while( *subst && (d_len > 0) ) {
if ((subst[0] == '\\') && isdigit(subst[1]) && (pmatch[subst[1]-'0'].rm_so != -1)) {
backref = subst[1]-'0';
size = pmatch[backref].rm_eo - pmatch[backref].rm_so;
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;
}
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 {
char *dst;
int dstlen;
char *tech;
int techlen;
char *txt;
int txtlen;
char *naptrinput;
char *dst; /* Destination part of URL from ENUM */
int dstlen; /* Length */
char *tech; /* Technology (from URL scheme) */
int techlen; /* Length */
char *txt; /* TXT record in TXT lookup */
int txtlen; /* Length */
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)
{
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");
#endif
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 {
if (answer == NULL) {
c->txt = NULL;
c->txtlen = 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)
{
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;
}
/*--- ast_get_enum: ENUM lookup */
int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen)
{
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);
context.naptrinput = naptrinput;
context.dst = dst;
context.naptrinput = naptrinput; /* The number */
context.dst = dst; /* Return string */
context.dstlen = dstlen;
context.tech = tech;
context.tech = tech; /* Return string */
context.techlen = techlen;
if (pos > 128)
......@@ -328,6 +348,9 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds
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)
{
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);
if (!s)
break;
ret = ast_search_dns(&context, tmp, C_IN, T_TXT, txt_callback);
if (ret > 0)
break;
......@@ -387,9 +411,11 @@ int ast_get_txt(struct ast_channel *chan, const char *number, char *dst, int dst
return ret;
}
/*--- enum_newtoplev: Add enum tree to linked list ---*/
static struct enum_search *enum_newtoplev(char *s)
{
struct enum_search *tmp;
tmp = malloc(sizeof(struct enum_search));
if (tmp) {
memset(tmp, 0, sizeof(struct enum_search));
......@@ -398,6 +424,7 @@ static struct enum_search *enum_newtoplev(char *s)
return tmp;
}
/*--- ast_enum_init: Initialize the ENUM support subsystem */
int ast_enum_init(void)
{
struct ast_config *cfg;
......
......@@ -14,7 +14,14 @@
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,
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer));
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer));
#endif /* _ASTERISK_DNS_H */
......@@ -3,19 +3,42 @@
*
* 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
* the GNU General Public License
*/
/*! \file enum.h
\brief DNS and ENUM functions
*/
#ifndef _ASTERISK_ENUM_H
#define _ASTERISK_ENUM_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);
/*! \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_enum_init(void);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment