Wed Oct 28 11:46:08 2009

Asterisk developer's documentation


enum.c File Reference

ENUM Support for Asterisk. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <ctype.h>
#include <regex.h>
#include "asterisk/enum.h"
#include "asterisk/dns.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/manager.h"

Include dependency graph for enum.c:

Go to the source code of this file.

Data Structures

struct  enum_search

Defines

#define ENUMLOOKUP_OPTIONS_COUNT   1
#define TOPLEV   "e164.arpa."

Functions

int ast_enum_init (void)
int ast_enum_reload (void)
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.
int ast_get_txt (struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen, char *txt, int txtlen)
 Lookup DNS TXT record (used by app TXTCIDnum.
static int enum_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer)
 Callback from ENUM lookup function.
static struct enum_searchenum_newtoplev (const char *s)
 Add enum tree to linked list.
static unsigned int parse_ie (char *data, unsigned int maxdatalen, unsigned char *src, unsigned int srclen)
 Parse NAPTR record information elements.
static int parse_naptr (char *dst, int dstsize, char *tech, int techsize, unsigned char *answer, int len, char *naptrinput)
 Parse DNS NAPTR record used in ENUM ---.
static int private_enum_init (int reload)
 Initialize the ENUM support subsystem.
static int txt_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer)
 Callback for TXT record lookup.

Variables

static ast_mutex_t enumlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static int enumver
static struct enum_searchtoplevs


Detailed Description

ENUM Support for Asterisk.

Author:
Mark Spencer <markster@digium.com>
Enum standards

Possible improvement
Todo:
Implement a caching mechanism for multile enum lookups

Definition in file enum.c.


Define Documentation

#define ENUMLOOKUP_OPTIONS_COUNT   1

Definition at line 307 of file enum.c.

Referenced by ast_get_enum(), and enum_callback().

#define TOPLEV   "e164.arpa."

The IETF Enum standard root, managed by the ITU

Definition at line 76 of file enum.c.

Referenced by private_enum_init().


Function Documentation

int ast_enum_init ( void   ) 

Definition at line 667 of file enum.c.

References private_enum_init().

Referenced by main().

00668 {
00669    return private_enum_init(0);
00670 }

int ast_enum_reload ( void   ) 

Definition at line 672 of file enum.c.

References private_enum_init().

00673 {
00674    return private_enum_init(1);
00675 }

int ast_get_enum ( struct ast_channel chan,
const char *  number,
char *  location,
int  maxloc,
char *  technology,
int  maxtech,
char *  suffix,
char *  options,
unsigned int  record,
struct enum_context **  argcontext 
)

Lookup entry in ENUM.

Parameters:
chan Channel
number E164 number with or without the leading +
location Number returned (or SIP uri)
maxloc Max length
technology Technology (from url scheme in response) You can set it to get particular answer RR, if there are many techs in DNS response, example: "sip" If you need any record, then set it to empty string
maxtech Max length
suffix Zone suffix (if is NULL then use enum.conf 'search' variable)
options Options ('c' to count number of NAPTR RR)
record The position of required RR in the answer list
argcontext Argument for caching results into an enum_context pointer (NULL is used for not caching)
Return values:
1 if found
0 if not found
-1 on hangup

Definition at line 380 of file enum.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_mutex_lock(), ast_mutex_unlock(), ast_search_dns(), context, enum_context::dst, enum_context::dstlen, enum_callback(), enumlock, ENUMLOOKUP_OPTIONS_COUNT, errno, enum_naptr_rr::naptr, enum_context::naptr_rrs, enum_context::naptr_rrs_count, enum_context::naptrinput, enum_search::next, enum_context::options, naptr::order, enum_context::position, naptr::pref, enum_naptr_rr::result, s, enum_naptr_rr::sort_pos, enum_naptr_rr::tech, enum_context::tech, enum_context::techlen, enum_search::toplev, toplevs, and version.

Referenced by enum_query_read(), and function_enum().

00381 {
00382    struct enum_context *context;
00383    char tmp[259 + 512];
00384    char naptrinput[512];
00385    int pos = strlen(number) - 1;
00386    int newpos = 0;
00387    int ret = -1;
00388    struct enum_search *s = NULL;
00389    int version = -1;
00390    /* for ISN rewrite */
00391    char *p1 = NULL;
00392    char *p2 = NULL;
00393    int k = 0;
00394    int i = 0;
00395    int z = 0;
00396 
00397    if (!(context = ast_calloc(1, sizeof(*context))))
00398       return -1;
00399 
00400    ast_copy_string(naptrinput, number[0] == 'n' ? number + 1 : number, sizeof(naptrinput));
00401 
00402    context->naptrinput = naptrinput;   /* The number */
00403    context->dst = dst;        /* Return string */
00404    context->dstlen = dstlen;
00405    context->tech = tech;
00406    context->techlen = techlen;
00407    context->options = 0;
00408    context->position = record;
00409    context->naptr_rrs = NULL;
00410    context->naptr_rrs_count = 0;
00411 
00412    if (options != NULL) {
00413       if (*options == 'c') {
00414          context->options = ENUMLOOKUP_OPTIONS_COUNT;
00415          context->position = 0;
00416       }
00417    }
00418 
00419    ast_debug(1, "ast_get_enum(): n='%s', tech='%s', suffix='%s', options='%d', record='%d'\n",
00420          number, tech, suffix, context->options, context->position);
00421 
00422    if (pos > 128)
00423       pos = 128;
00424 
00425    /* ISN rewrite */
00426    p1 = strchr(number, '*');
00427 
00428    if (number[0] == 'n') { /* do not perform ISN rewrite ('n' is testing flag) */
00429       p1 = NULL;
00430       k = 1; /* strip 'n' from number */
00431    }
00432 
00433    if (p1 != NULL) {
00434       p2 = p1 + 1;
00435       while (p1 > number){
00436          p1--;
00437          tmp[newpos++] = *p1;
00438          tmp[newpos++] = '.';
00439       }
00440       if (*p2) {
00441          while (*p2 && newpos < 128){
00442             tmp[newpos++] = *p2;
00443             p2++;
00444          }
00445          tmp[newpos++] = '.';
00446       }
00447 
00448    } else {
00449       while (pos >= k) {
00450          if (isdigit(number[pos])) {
00451             tmp[newpos++] = number[pos];
00452             tmp[newpos++] = '.';
00453          }
00454          pos--;
00455       }
00456    }
00457 
00458    if (chan && ast_autoservice_start(chan) < 0) {
00459       ast_free(context);
00460       return -1;
00461    }
00462 
00463    if (suffix) {
00464       ast_copy_string(tmp + newpos, suffix, sizeof(tmp) - newpos);
00465       ret = ast_search_dns(context, tmp, C_IN, T_NAPTR, enum_callback);
00466       ast_debug(1, "ast_get_enum: ast_search_dns(%s) returned %d\n", tmp, ret);
00467    } else {
00468       ret = -1;      /* this is actually dead code since the demise of app_enum.c */
00469       for (;;) {
00470          ast_mutex_lock(&enumlock);
00471          if (version != enumver) {
00472             /* Ooh, a reload... */
00473             s = toplevs;
00474             version = enumver;
00475          } else {
00476             s = s->next;
00477          }
00478          ast_mutex_unlock(&enumlock);
00479 
00480          if (!s)
00481             break;
00482    
00483          ast_copy_string(tmp + newpos, s->toplev, sizeof(tmp) - newpos);
00484          ret = ast_search_dns(&context, tmp, C_IN, T_NAPTR, enum_callback);
00485          ast_debug(1, "ast_get_enum: ast_search_dns(%s) returned %d\n", tmp, ret);
00486          if (ret > 0)
00487             break;
00488       }
00489    }
00490 
00491    if (ret < 0) {
00492       ast_debug(1, "No such number found: %s (%s)\n", tmp, strerror(errno));
00493       strcpy(dst, "0");
00494       ret = 0;
00495    }
00496 
00497    if (context->naptr_rrs_count >= context->position && ! (context->options & ENUMLOOKUP_OPTIONS_COUNT)) {
00498       /* sort array by NAPTR order/preference */
00499       for (k = 0; k < context->naptr_rrs_count; k++) {
00500          for (i = 0; i < context->naptr_rrs_count; i++) {
00501             /* use order first and then preference to compare */
00502             if ((ntohs(context->naptr_rrs[k].naptr.order) < ntohs(context->naptr_rrs[i].naptr.order)
00503                   && context->naptr_rrs[k].sort_pos > context->naptr_rrs[i].sort_pos)
00504                || (ntohs(context->naptr_rrs[k].naptr.order) > ntohs(context->naptr_rrs[i].naptr.order)
00505                   && context->naptr_rrs[k].sort_pos < context->naptr_rrs[i].sort_pos)){
00506                z = context->naptr_rrs[k].sort_pos;
00507                context->naptr_rrs[k].sort_pos = context->naptr_rrs[i].sort_pos;
00508                context->naptr_rrs[i].sort_pos = z;
00509                continue;
00510             }
00511             if (ntohs(context->naptr_rrs[k].naptr.order) == ntohs(context->naptr_rrs[i].naptr.order)) {
00512                if ((ntohs(context->naptr_rrs[k].naptr.pref) < ntohs(context->naptr_rrs[i].naptr.pref)
00513                      && context->naptr_rrs[k].sort_pos > context->naptr_rrs[i].sort_pos)
00514                   || (ntohs(context->naptr_rrs[k].naptr.pref) > ntohs(context->naptr_rrs[i].naptr.pref)
00515                      && context->naptr_rrs[k].sort_pos < context->naptr_rrs[i].sort_pos)){
00516                   z = context->naptr_rrs[k].sort_pos;
00517                   context->naptr_rrs[k].sort_pos = context->naptr_rrs[i].sort_pos;
00518                   context->naptr_rrs[i].sort_pos = z;
00519                }
00520             }
00521          }
00522       }
00523       for (k = 0; k < context->naptr_rrs_count; k++) {
00524          if (context->naptr_rrs[k].sort_pos == context->position - 1) {
00525             ast_copy_string(context->dst, context->naptr_rrs[k].result, dstlen);
00526             ast_copy_string(context->tech, context->naptr_rrs[k].tech, techlen);
00527             break;
00528          }
00529       }
00530    } else if (!(context->options & ENUMLOOKUP_OPTIONS_COUNT)) {
00531       context->dst[0] = 0;
00532    }
00533    if (chan)
00534       ret |= ast_autoservice_stop(chan);
00535 
00536    if (!argcontext) {
00537       for (k = 0; k < context->naptr_rrs_count; k++) {
00538          ast_free(context->naptr_rrs[k].result);
00539          ast_free(context->naptr_rrs[k].tech);
00540       }
00541       ast_free(context->naptr_rrs);
00542       ast_free(context);
00543    } else
00544       *argcontext = context;
00545 
00546    return ret;
00547 }

int ast_get_txt ( struct ast_channel chan,
const char *  number,
char *  location,
int  maxloc,
char *  technology,
int  maxtech,
char *  txt,
int  maxtxt 
)

Lookup DNS TXT record (used by app TXTCIDnum.

Parameters:
chan Channel
number E164 number with or without the leading +
location Number returned (or SIP uri)
maxloc Max length of number
technology Technology (not used in TXT records)
maxtech Max length
txt Text string (return value)
maxtxt Max length of "txt"

Definition at line 550 of file enum.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_search_dns(), enum_context::dst, enum_context::dstlen, enumlock, errno, enum_context::naptrinput, enum_search::next, s, enum_context::tech, enum_context::techlen, enum_search::toplev, toplevs, enum_context::txt, txt_callback(), enum_context::txtlen, and version.

Referenced by function_txtcidname().

00551 {
00552    struct enum_context context;
00553    char tmp[259 + 512];
00554    char naptrinput[512] = "+";
00555    int pos = strlen(number) - 1;
00556    int newpos = 0;
00557    int ret = -1;
00558    struct enum_search *s = NULL;
00559    int version = -1;
00560 
00561    strncat(naptrinput, number, sizeof(naptrinput) - 2);
00562 
00563    context.naptrinput = naptrinput;
00564    context.dst = dst;
00565    context.dstlen = dstlen;
00566    context.tech = tech;
00567    context.techlen = techlen;
00568    context.txt = txt;
00569    context.txtlen = txtlen;
00570 
00571    if (pos > 128)
00572       pos = 128;
00573    while (pos >= 0) {
00574       tmp[newpos++] = number[pos--];
00575       tmp[newpos++] = '.';
00576    }
00577 
00578    if (chan && ast_autoservice_start(chan) < 0)
00579       return -1;
00580 
00581    for (;;) {
00582       ast_mutex_lock(&enumlock);
00583       if (version != enumver) {
00584          /* Ooh, a reload... */
00585          s = toplevs;
00586          version = enumver;
00587       } else {
00588          s = s->next;
00589       }
00590       if (s) {
00591          ast_copy_string(tmp + newpos, s->toplev, sizeof(tmp) - newpos);
00592       }
00593       ast_mutex_unlock(&enumlock);
00594       if (!s)
00595          break;
00596 
00597       ret = ast_search_dns(&context, tmp, C_IN, T_TXT, txt_callback);
00598       if (ret > 0)
00599          break;
00600    }
00601    if (ret < 0) {
00602       ast_debug(2, "No such number found in ENUM: %s (%s)\n", tmp, strerror(errno));
00603       ret = 0;
00604    }
00605    if (chan)
00606       ret |= ast_autoservice_stop(chan);
00607    return ret;
00608 }

static int enum_callback ( void *  context,
unsigned char *  answer,
int  len,
unsigned char *  fullanswer 
) [static]

Callback from ENUM lookup function.

Definition at line 343 of file enum.c.

References ast_log(), ast_realloc, ast_strdup, ast_strlen_zero(), enum_context::dst, enum_context::dstlen, ENUMLOOKUP_OPTIONS_COUNT, LOG_WARNING, enum_naptr_rr::naptr, enum_context::naptr_rrs, enum_context::naptr_rrs_count, enum_context::naptrinput, enum_context::options, parse_naptr(), enum_context::position, enum_naptr_rr::result, enum_naptr_rr::sort_pos, enum_naptr_rr::tech, enum_context::tech, and enum_context::techlen.

Referenced by ast_get_enum().

00344 {
00345    struct enum_context *c = context;
00346    void *p = NULL;
00347    int res;
00348 
00349    res = parse_naptr(c->dst, c->dstlen, c->tech, c->techlen, answer, len, c->naptrinput);
00350 
00351    if (res < 0) {
00352       ast_log(LOG_WARNING, "Failed to parse naptr :(\n");
00353       return -1;
00354    } else if (res > 0 && !ast_strlen_zero(c->dst)){ /* ok, we got needed NAPTR */
00355       if (c->options & ENUMLOOKUP_OPTIONS_COUNT){ /* counting RRs */
00356          c->position++;
00357          snprintf(c->dst, c->dstlen, "%d", c->position);
00358       } else  {
00359          if ((p = ast_realloc(c->naptr_rrs, sizeof(*c->naptr_rrs) * (c->naptr_rrs_count + 1)))) {
00360             c->naptr_rrs = p;
00361             memcpy(&c->naptr_rrs[c->naptr_rrs_count].naptr, answer, sizeof(c->naptr_rrs->naptr));
00362             c->naptr_rrs[c->naptr_rrs_count].result = ast_strdup(c->dst);
00363             c->naptr_rrs[c->naptr_rrs_count].tech = ast_strdup(c->tech);
00364             c->naptr_rrs[c->naptr_rrs_count].sort_pos = c->naptr_rrs_count;
00365             c->naptr_rrs_count++;
00366          }
00367          c->dst[0] = 0;
00368       }
00369       return 0;
00370    }
00371 
00372    if (c->options & ENUMLOOKUP_OPTIONS_COUNT)   { /* counting RRs */
00373       snprintf(c->dst, c->dstlen, "%d", c->position);
00374    }
00375 
00376    return 0;
00377 }

static struct enum_search* enum_newtoplev ( const char *  s  )  [static, read]

Add enum tree to linked list.

Definition at line 611 of file enum.c.

References ast_calloc, ast_copy_string(), and enum_search::toplev.

Referenced by private_enum_init().

00612 {
00613    struct enum_search *tmp;
00614 
00615    if ((tmp = ast_calloc(1, sizeof(*tmp)))) {      
00616       ast_copy_string(tmp->toplev, s, sizeof(tmp->toplev));
00617    }
00618    return tmp;
00619 }

static unsigned int parse_ie ( char *  data,
unsigned int  maxdatalen,
unsigned char *  src,
unsigned int  srclen 
) [static]

Parse NAPTR record information elements.

Definition at line 89 of file enum.c.

References ast_log(), len(), and LOG_WARNING.

Referenced by parse_naptr().

00090 {
00091    unsigned int len, olen;
00092 
00093    len = olen = (unsigned int) src[0];
00094    src++;
00095    srclen--;
00096 
00097    if (len > srclen) {
00098       ast_log(LOG_WARNING, "ENUM parsing failed: Wanted %d characters, got %d\n", len, srclen);
00099       return -1;
00100    }
00101 
00102    if (len > maxdatalen)
00103       len = maxdatalen;
00104    memcpy(data, src, len);
00105 
00106    return olen + 1;
00107 }

static int parse_naptr ( char *  dst,
int  dstsize,
char *  tech,
int  techsize,
unsigned char *  answer,
int  len,
char *  naptrinput 
) [static]

Parse DNS NAPTR record used in ENUM ---.

Definition at line 110 of file enum.c.

References ARRAY_LEN, ast_copy_string(), ast_debug, ast_log(), LOG_WARNING, and parse_ie().

Referenced by enum_callback().

00111 {
00112    char tech_return[80];
00113    unsigned char *oanswer = answer;
00114    char flags[512] = "";
00115    char services[512] = "";
00116    char *p;
00117    char regexp[512] = "";
00118    char repl[512] = "";
00119    char tempdst[512] = "";
00120    char errbuff[512] = "";
00121    char delim;
00122    char *delim2;
00123    char *pattern, *subst, *d;
00124    int res;
00125    int regexp_len, rc;
00126    int size, matchindex; /* size is the size of the backreference sub. */
00127    int d_len = sizeof(tempdst) - 1;
00128    static const int max_bt = 10; /* max num of regexp backreference allowed, must remain 10 to guarantee a valid backreference index */
00129    regex_t preg;
00130    regmatch_t pmatch[max_bt];
00131 
00132    tech_return[0] = '\0';
00133 
00134    dst[0] = '\0';
00135 
00136    if (len < sizeof(struct naptr)) {
00137       ast_log(LOG_WARNING, "NAPTR record length too short\n");
00138       return -1;
00139    }
00140    answer += sizeof(struct naptr);
00141    len -= sizeof(struct naptr);
00142    if ((res = parse_ie(flags, sizeof(flags) - 1, answer, len)) < 0) {
00143       ast_log(LOG_WARNING, "Failed to get flags from NAPTR record\n");
00144       return -1;
00145    } else {
00146       answer += res;
00147       len -= res;
00148    }
00149    if ((res = parse_ie(services, sizeof(services) - 1, answer, len)) < 0) {
00150       ast_log(LOG_WARNING, "Failed to get services from NAPTR record\n");
00151       return -1;
00152    } else {
00153       answer += res;
00154       len -= res;
00155    }
00156    if ((res = parse_ie(regexp, sizeof(regexp) - 1, answer, len)) < 0) {
00157       ast_log(LOG_WARNING, "Failed to get regexp from NAPTR record\n");
00158       return -1;
00159    } else {
00160       answer += res;
00161       len -= res;
00162    }
00163 
00164    if ((res = dn_expand(oanswer, answer + len, answer, repl, sizeof(repl) - 1)) < 0) {
00165       ast_log(LOG_WARNING, "Failed to expand hostname\n");
00166       return -1;
00167    }
00168 
00169    ast_debug(3, "NAPTR input='%s', flags='%s', services='%s', regexp='%s', repl='%s'\n",
00170       naptrinput, flags, services, regexp, repl);
00171 
00172    if (tolower(flags[0]) != 'u') {
00173       ast_log(LOG_WARNING, "NAPTR Flag must be 'U' or 'u'.\n");
00174       return -1;
00175    }
00176 
00177    p = strstr(services, "e2u+");
00178    if (p == NULL)
00179       p = strstr(services, "E2U+");
00180    if (p){
00181       p = p + 4;
00182       if (strchr(p, ':')){
00183          p = strchr(p, ':') + 1;
00184       }
00185       ast_copy_string(tech_return, p, sizeof(tech_return));
00186    } else {
00187 
00188       p = strstr(services, "+e2u");
00189       if (p == NULL)
00190          p = strstr(services, "+E2U");
00191       if (p) {
00192          *p = 0;
00193          p = strchr(services, ':');
00194          if (p)
00195             *p = 0;
00196          ast_copy_string(tech_return, services, sizeof(tech_return));
00197       }
00198    }
00199 
00200    regexp_len = strlen(regexp);
00201    if (regexp_len < 7) {
00202       ast_log(LOG_WARNING, "Regex too short to be meaningful.\n");
00203       return -1;
00204    }
00205 
00206    /* this takes the first character of the regexp (which is a delimiter) 
00207     * and uses that character to find the index of the second delimiter */
00208    delim = regexp[0];
00209    delim2 = strchr(regexp + 1, delim);
00210    if ((delim2 == NULL) || (regexp[regexp_len - 1] != delim)) {  /* is the second delimiter found, and is the end of the regexp a delimiter */
00211       ast_log(LOG_WARNING, "Regex delimiter error (on \"%s\").\n", regexp);
00212       return -1;
00213    } else if (strchr((delim2 + 1), delim) == NULL) { /* if the second delimiter is found, make sure there is a third instance.  this could be the end one instead of the middle */
00214       ast_log(LOG_WARNING, "Regex delimiter error (on \"%s\").\n", regexp);
00215       return -1;
00216    }
00217    pattern = regexp + 1;   /* pattern is the regex without the begining and ending delimiter */
00218    *delim2 = 0;    /* zero out the middle delimiter */
00219    subst   = delim2 + 1; /* dst substring is everything after the second delimiter. */
00220    regexp[regexp_len - 1] = 0; /* zero out the last delimiter */
00221 
00222 /*
00223  * now do the regex wizardry.
00224  */
00225 
00226    if (regcomp(&preg, pattern, REG_EXTENDED | REG_NEWLINE)) {
00227       ast_log(LOG_WARNING, "NAPTR Regex compilation error (regex = \"%s\").\n", regexp);
00228       return -1;
00229    }
00230 
00231    if (preg.re_nsub > ARRAY_LEN(pmatch)) {
00232       ast_log(LOG_WARNING, "NAPTR Regex compilation error: too many subs.\n");
00233       regfree(&preg);
00234       return -1;
00235    }
00236    /* pmatch is an array containing the substring indexes for the regex backreference sub.
00237     * max_bt is the maximum number of backreferences allowed to be stored in pmatch */
00238    if ((rc = regexec(&preg, (char *) naptrinput, max_bt, pmatch, 0))) {
00239       regerror(rc, &preg, errbuff, sizeof(errbuff));
00240       ast_log(LOG_WARNING, "NAPTR Regex match failed. Reason: %s\n", errbuff);
00241       regfree(&preg);
00242       return -1;
00243    }
00244    regfree(&preg);
00245 
00246    d = tempdst;
00247    d_len--;
00248 
00249    /* perform the backreference sub. Search the subst for backreferences,
00250     * when a backreference is found, retrieve the backreferences number.
00251     * use the backreference number as an index for pmatch to retrieve the
00252     * beginning and ending indexes of the substring to insert as the backreference.
00253     * if no backreference is found, continue copying the subst into tempdst */
00254    while (*subst && (d_len > 0)) {
00255       if ((subst[0] == '\\') && isdigit(subst[1])) { /* is this character the beginning of a backreference */
00256          matchindex = (int) (subst[1] - '0');
00257          if (matchindex >= ARRAY_LEN(pmatch)) {
00258             ast_log(LOG_WARNING, "Error during regex substitution. Invalid pmatch index.\n");
00259             return -1;
00260          }
00261          /* pmatch len is 10. we are garanteed a single char 0-9 is a valid index */
00262          size = pmatch[matchindex].rm_eo - pmatch[matchindex].rm_so;
00263          if (size > d_len) {
00264             ast_log(LOG_WARNING, "Not enough space during NAPTR regex substitution.\n");
00265             return -1;
00266          }
00267          /* are the pmatch indexes valid for the input length */
00268          if ((strlen((char *) naptrinput) >= pmatch[matchindex].rm_eo) && (pmatch[matchindex].rm_so <= pmatch[matchindex].rm_eo)) {
00269             memcpy(d, (naptrinput + (int) pmatch[matchindex].rm_so), size);  /* copy input substring into backreference marker */
00270             d_len -= size;
00271             subst += 2;  /* skip over backreference characters to next valid character */
00272             d += size;
00273          } else {
00274             ast_log(LOG_WARNING, "Error during regex substitution. Invalid backreference index.\n");
00275             return -1;
00276          }
00277       } else if (isprint(*subst)) {
00278          *d++ = *subst++;
00279          d_len--;
00280       } else {
00281          ast_log(LOG_WARNING, "Error during regex substitution.\n");
00282          return -1;
00283       }
00284    }
00285    *d = 0;
00286    ast_copy_string((char *) dst, tempdst, dstsize);
00287    dst[dstsize - 1] = '\0';
00288 
00289    if (*tech != '\0'){ /* check if it is requested NAPTR */
00290       if (!strncasecmp(tech, "ALL", techsize)){
00291          return 1; /* return or count any RR */
00292       }
00293       if (!strncasecmp(tech_return, tech, sizeof(tech_return)<techsize?sizeof(tech_return):techsize)){
00294          ast_copy_string(tech, tech_return, techsize);
00295          return 1; /* we got out RR */
00296       } else { /* go to the next RR in the DNS answer */
00297          return 0;
00298       }
00299    }
00300 
00301    /* tech was not specified, return first parsed RR */
00302    ast_copy_string(tech, tech_return, techsize);
00303    return 1;
00304 }

static int private_enum_init ( int  reload  )  [static]

Initialize the ENUM support subsystem.

Definition at line 622 of file enum.c.

References ast_config_destroy(), ast_config_load, ast_free, ast_mutex_lock(), ast_mutex_unlock(), ast_variable_browse(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, enum_newtoplev(), enumlock, EVENT_FLAG_SYSTEM, manager_event, ast_variable::name, ast_variable::next, enum_search::next, s, TOPLEV, toplevs, and ast_variable::value.

Referenced by ast_enum_init(), and ast_enum_reload().

00623 {
00624    struct ast_config *cfg;
00625    struct enum_search *s, *sl;
00626    struct ast_variable *v;
00627    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00628 
00629    if ((cfg = ast_config_load("enum.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
00630       return 0;
00631 
00632    /* Destroy existing list */
00633    ast_mutex_lock(&enumlock);
00634    s = toplevs;
00635    while (s) {
00636       sl = s;
00637       s = s->next;
00638       ast_free(sl);
00639    }
00640    toplevs = NULL;
00641    if (cfg) {
00642       sl = NULL;
00643       v = ast_variable_browse(cfg, "general");
00644       while (v) {
00645          if (!strcasecmp(v->name, "search")) {
00646             s = enum_newtoplev(v->value);
00647             if (s) {
00648                if (sl)
00649                   sl->next = s;
00650                else
00651                   toplevs = s;
00652                sl = s;
00653             }
00654          }
00655          v = v->next;
00656       }
00657       ast_config_destroy(cfg);
00658    } else {
00659       toplevs = enum_newtoplev(TOPLEV);
00660    }
00661    enumver++;
00662    ast_mutex_unlock(&enumlock);
00663    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Enum\r\nStatus: Enabled\r\nMessage: ENUM reload Requested\r\n");
00664    return 0;
00665 }

static int txt_callback ( void *  context,
unsigned char *  answer,
int  len,
unsigned char *  fullanswer 
) [static]

Callback for TXT record lookup.

Definition at line 311 of file enum.c.

References ast_copy_string(), enum_context::txt, and enum_context::txtlen.

Referenced by ast_get_txt().

00312 {
00313    struct enum_context *c = (struct enum_context *)context;
00314 
00315    if (answer == NULL) {
00316       c->txt = NULL;
00317       c->txtlen = 0;
00318       return 0;
00319    }
00320 
00321    /* skip over first byte, as for some reason it's a vertical tab character */
00322    answer += 1;
00323    len -= 1;
00324 
00325    /* answer is not null-terminated, but should be */
00326    /* this is safe to do, as answer has extra bytes on the end we can
00327     * safely overwrite with a null */
00328    answer[len] = '\0';
00329    /* now increment len so that len includes the null, so that we can
00330     * compare apples to apples */
00331    len +=1;
00332 
00333    /* finally, copy the answer into c->txt */
00334    ast_copy_string(c->txt, (const char *) answer, len < c->txtlen ? len : (c->txtlen));
00335 
00336    /* just to be safe, let's make sure c->txt is null terminated */
00337    c->txt[(c->txtlen) - 1] = '\0';
00338 
00339    return 1;
00340 }


Variable Documentation

ast_mutex_t enumlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 86 of file enum.c.

Referenced by ast_get_enum(), ast_get_txt(), and private_enum_init().

int enumver [static]

Definition at line 84 of file enum.c.

struct enum_search * toplevs [static]


Generated on Wed Oct 28 11:46:08 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6