Index: enum.c =================================================================== RCS file: /usr/cvsroot/asterisk/enum.c,v retrieving revision 1.21 diff -u -r1.21 enum.c --- enum.c 25 Jan 2005 06:10:19 -0000 1.21 +++ enum.c 1 Mar 2005 21:08:00 -0000 @@ -1,7 +1,7 @@ /* * ENUM Support for Asterisk * - * Copyright (C) 2003 Digium + * Copyright (C) 2003-2005, Digium, inc * * Written by Mark Spencer * @@ -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 @@ 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 @@ 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 @@ 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 @@ */ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ return tmp; } +/*--- ast_enum_init: Initialize the ENUM support subsystem */ int ast_enum_init(void) { struct ast_config *cfg; Index: dns.c =================================================================== RCS file: /usr/cvsroot/asterisk/dns.c,v retrieving revision 1.10 diff -u -r1.10 dns.c --- dns.c 22 Jun 2004 20:11:15 -0000 1.10 +++ dns.c 1 Mar 2005 21:08:00 -0000 @@ -89,9 +89,10 @@ 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 @@ #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 @@ #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 Index: include/asterisk/enum.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/enum.h,v retrieving revision 1.3 diff -u -r1.3 enum.h --- include/asterisk/enum.h 16 May 2004 18:12:16 -0000 1.3 +++ include/asterisk/enum.h 1 Mar 2005 21:08:00 -0000 @@ -3,19 +3,42 @@ * * ENUM support * - * Copyright (C) 1999, Mark Spencer + * Copyright (C) 1999-2005, Digium, inc * - * Mark Spencer + * Mark Spencer * * 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 -/* 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); Index: include/asterisk/dns.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/dns.h,v retrieving revision 1.1 diff -u -r1.1 dns.h --- include/asterisk/dns.h 27 Sep 2003 00:37:07 -0000 1.1 +++ include/asterisk/dns.h 1 Mar 2005 21:08:00 -0000 @@ -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 */