Thu Oct 11 06:43:27 2012

Asterisk developer's documentation


enum.c File Reference

ENUM Support for Asterisk. More...

#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <regex.h>
#include <unistd.h>
#include <errno.h>
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/enum.h"
#include "asterisk/dns.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"

Include dependency graph for enum.c:

Go to the source code of this file.

Data Structures

struct  enum_context
struct  enum_naptr_rr
struct  enum_search
struct  naptr

Defines

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

Functions

int ast_enum_init (void)
 Initialize the ENUM support subsystem.
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)
 ENUM lookup.
int ast_get_txt (struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen, char *txt, int txtlen)
 Get TXT record from DNS. Really has nothing to do with enum, but anyway...
static int enum_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer)
 Callback from ENUM lookup function.
static struct enum_searchenum_newtoplev (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 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 316 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 80 of file enum.c.

Referenced by ast_enum_init().


Function Documentation

int ast_enum_init ( void   ) 

Initialize the ENUM support subsystem.

Definition at line 646 of file enum.c.

References ast_config_destroy(), ast_config_load(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_browse(), enum_newtoplev(), enumlock, free, ast_variable::name, ast_variable::next, enum_search::next, s, TOPLEV, toplevs, and ast_variable::value.

Referenced by ast_enum_reload(), and main().

00647 {
00648    struct ast_config *cfg;
00649    struct enum_search *s, *sl;
00650    struct ast_variable *v;
00651 
00652    /* Destroy existing list */
00653    ast_mutex_lock(&enumlock);
00654    s = toplevs;
00655    while(s) {
00656       sl = s;
00657       s = s->next;
00658       free(sl);
00659    }
00660    toplevs = NULL;
00661    cfg = ast_config_load("enum.conf");
00662    if (cfg) {
00663       sl = NULL;
00664       v = ast_variable_browse(cfg, "general");
00665       while(v) {
00666          if (!strcasecmp(v->name, "search")) {
00667             s = enum_newtoplev(v->value);
00668             if (s) {
00669                if (sl)
00670                   sl->next = s;
00671                else
00672                   toplevs = s;
00673                sl = s;
00674             }
00675          }
00676          v = v->next;
00677       }
00678       ast_config_destroy(cfg);
00679    } else {
00680       toplevs = enum_newtoplev(TOPLEV);
00681    }
00682    enumver++;
00683    ast_mutex_unlock(&enumlock);
00684    return 0;
00685 }

int ast_enum_reload ( void   ) 

Definition at line 687 of file enum.c.

References ast_enum_init().

00688 {
00689    return ast_enum_init();
00690 }

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 
)

ENUM lookup.

Lookup entry in ENUM Returns 1 if found, 0 if not found, -1 on hangup.

Definition at line 409 of file enum.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_search_dns(), enum_context::dst, enum_context::dstlen, enum_callback(), enumlock, ENUMLOOKUP_OPTIONS_COUNT, errno, free, LOG_DEBUG, 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, and toplevs.

Referenced by function_enum().

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

int ast_get_txt ( struct ast_channel chan,
const char *  number,
char *  dst,
int  dstlen,
char *  tech,
int  techlen,
char *  txt,
int  txtlen 
)

Get TXT record from DNS. Really has nothing to do with enum, but anyway...

Lookup DNS TXT record (used by app TXTCIDnum.

Definition at line 573 of file enum.c.

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

Referenced by function_txtcidname().

00574 {
00575    struct enum_context context;
00576    char tmp[259 + 512];
00577    char naptrinput[512] = "+";
00578    int pos = strlen(number) - 1;
00579    int newpos = 0;
00580    int ret = -1;
00581    struct enum_search *s = NULL;
00582    int version = -1;
00583 
00584    strncat(naptrinput, number, sizeof(naptrinput) - 2);
00585 
00586    context.naptrinput = naptrinput;
00587    context.dst = dst;
00588    context.dstlen = dstlen;
00589    context.tech = tech;
00590    context.techlen = techlen;
00591    context.txt = txt;
00592    context.txtlen = txtlen;
00593 
00594    if (pos > 128)
00595       pos = 128;
00596    while (pos >= 0) {
00597       tmp[newpos++] = number[pos--];
00598       tmp[newpos++] = '.';
00599    }
00600 
00601    if (chan && ast_autoservice_start(chan) < 0)
00602       return -1;
00603 
00604    for (;;) {
00605       ast_mutex_lock(&enumlock);
00606       if (version != enumver) {
00607          /* Ooh, a reload... */
00608          s = toplevs;
00609          version = enumver;
00610       } else {
00611          s = s->next;
00612       }
00613       if (s) {
00614          ast_copy_string(tmp + newpos, s->toplev, sizeof(tmp) - newpos);
00615       }
00616       ast_mutex_unlock(&enumlock);
00617       if (!s)
00618          break;
00619 
00620       ret = ast_search_dns(&context, tmp, C_IN, T_TXT, txt_callback);
00621       if (ret > 0)
00622          break;
00623    }
00624    if (ret < 0) {
00625       if (option_debug > 1)
00626          ast_log(LOG_DEBUG, "No such number found in ENUM: %s (%s)\n", tmp, strerror(errno));
00627       ret = 0;
00628    }
00629    if (chan)
00630       ret |= ast_autoservice_stop(chan);
00631    return ret;
00632 }

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

Callback from ENUM lookup function.

Definition at line 372 of file enum.c.

References ast_log(), ast_realloc, 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, strdup, enum_naptr_rr::tech, enum_context::tech, and enum_context::techlen.

Referenced by ast_get_enum().

00373 {
00374    struct enum_context *c = context;
00375    void *p = NULL;
00376    int res;
00377 
00378    res = parse_naptr(c->dst, c->dstlen, c->tech, c->techlen, answer, len, c->naptrinput);
00379 
00380    if (res < 0) {
00381       ast_log(LOG_WARNING, "Failed to parse naptr :(\n");
00382       return -1;
00383    } else if (res > 0 && !ast_strlen_zero(c->dst)){ /* ok, we got needed NAPTR */
00384       if (c->options & ENUMLOOKUP_OPTIONS_COUNT){ /* counting RRs */
00385          c->position++;
00386          snprintf(c->dst, c->dstlen, "%d", c->position);
00387       } else  {
00388          if ((p = ast_realloc(c->naptr_rrs, sizeof(*c->naptr_rrs) * (c->naptr_rrs_count + 1)))) {
00389             c->naptr_rrs = p;
00390             memcpy(&c->naptr_rrs[c->naptr_rrs_count].naptr, answer, sizeof(c->naptr_rrs->naptr));
00391             c->naptr_rrs[c->naptr_rrs_count].result = strdup(c->dst);
00392             c->naptr_rrs[c->naptr_rrs_count].tech = strdup(c->tech);
00393             c->naptr_rrs[c->naptr_rrs_count].sort_pos = c->naptr_rrs_count;
00394             c->naptr_rrs_count++;
00395          }
00396          c->dst[0] = 0;
00397       }
00398       return 0;
00399    }
00400 
00401    if (c->options & ENUMLOOKUP_OPTIONS_COUNT)   { /* counting RRs */
00402       snprintf(c->dst, c->dstlen, "%d", c->position);
00403    }
00404 
00405    return 0;
00406 }

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

Add enum tree to linked list.

Definition at line 635 of file enum.c.

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

Referenced by ast_enum_init().

00636 {
00637    struct enum_search *tmp;
00638 
00639    if ((tmp = ast_calloc(1, sizeof(*tmp)))) {      
00640       ast_copy_string(tmp->toplev, s, sizeof(tmp->toplev));
00641    }
00642    return tmp;
00643 }

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 98 of file enum.c.

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

Referenced by parse_naptr().

00099 {
00100    unsigned int len, olen;
00101 
00102    len = olen = (unsigned int) src[0];
00103    src++;
00104    srclen--;
00105 
00106    if (len > srclen) {
00107       ast_log(LOG_WARNING, "ENUM parsing failed: Wanted %d characters, got %d\n", len, srclen);
00108       return -1;
00109    }
00110 
00111    if (len > maxdatalen)
00112       len = maxdatalen;
00113    memcpy(data, src, len);
00114 
00115    return olen + 1;
00116 }

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 119 of file enum.c.

References ARRAY_LEN, ast_copy_string(), ast_log(), LOG_DEBUG, LOG_WARNING, option_debug, and parse_ie().

Referenced by enum_callback().

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

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

Callback for TXT record lookup.

Definition at line 340 of file enum.c.

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

Referenced by ast_get_txt().

00341 {
00342    struct enum_context *c = (struct enum_context *)context;
00343 
00344    if (answer == NULL) {
00345       c->txt = NULL;
00346       c->txtlen = 0;
00347       return 0;
00348    }
00349 
00350    /* skip over first byte, as for some reason it's a vertical tab character */
00351    answer += 1;
00352    len -= 1;
00353 
00354    /* answer is not null-terminated, but should be */
00355    /* this is safe to do, as answer has extra bytes on the end we can
00356     * safely overwrite with a null */
00357    answer[len] = '\0';
00358    /* now increment len so that len includes the null, so that we can
00359     * compare apples to apples */
00360    len +=1;
00361 
00362    /* finally, copy the answer into c->txt */
00363    ast_copy_string(c->txt, (const char *) answer, len < c->txtlen ? len : (c->txtlen));
00364 
00365    /* just to be safe, let's make sure c->txt is null terminated */
00366    c->txt[(c->txtlen)-1] = '\0';
00367 
00368    return 1;
00369 }


Variable Documentation

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

Definition at line 90 of file enum.c.

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

int enumver [static]

Definition at line 88 of file enum.c.

struct enum_search * toplevs [static]


Generated on Thu Oct 11 06:43:28 2012 for Asterisk - the Open Source PBX by  doxygen 1.5.6