Sat Mar 10 01:55:21 2012

Asterisk developer's documentation


enum.h File Reference

DNS and ENUM functions. More...

#include "asterisk/channel.h"

Go to the source code of this file.

Data Structures

struct  enum_context
struct  enum_naptr_rr
struct  naptr

Functions

int ast_enum_init (void)
int ast_enum_reload (void)
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.
int ast_get_txt (struct ast_channel *chan, const char *number, char *txt, int maxtxt, char *suffix)
 Lookup DNS TXT record (used by app TXTCIDnum).


Detailed Description

DNS and ENUM functions.

Definition in file enum.h.


Function Documentation

int ast_enum_init ( void   ) 

Definition at line 999 of file enum.c.

References private_enum_init().

Referenced by main().

01000 {
01001    return private_enum_init(0);
01002 }

int ast_enum_reload ( void   ) 

Definition at line 1004 of file enum.c.

References private_enum_init().

01005 {
01006    return private_enum_init(1);
01007 }

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 "ALL" string
maxtech Max length
suffix Zone suffix (WARNING: No defaults here any more)
options Options 'c' - Count number of NAPTR RR number - Position of the requested RR in the answer list 'u' - Full URI return (does not strip URI scheme) 'i' - Infrastructure ENUM lookup 's' - ISN based lookup 'd' - Direct DNS query
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 628 of file enum.c.

References ast_autoservice_start(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_search_dns(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), blr_ebl(), blr_txt(), cclen(), context, enum_callback(), enumlock, ENUMLOOKUP_BLR_CC, ENUMLOOKUP_BLR_EBL, ENUMLOOKUP_BLR_TXT, ENUMLOOKUP_OPTIONS_COUNT, ENUMLOOKUP_OPTIONS_DIRECT, ENUMLOOKUP_OPTIONS_IENUM, ENUMLOOKUP_OPTIONS_ISN, errno, LOG_WARNING, and enum_context::naptrinput.

Referenced by enum_query_read(), and function_enum().

00629 {
00630    struct enum_context *context;
00631    char tmp[512];
00632    char domain[256];
00633    char left[128];
00634    char middle[128];
00635    char naptrinput[128];
00636    char apex[128] = "";
00637    int ret = -1;
00638    /* for ISN rewrite */
00639    char *p1 = NULL;
00640    char *p2 = NULL;
00641    char *p3 = NULL;
00642    int k = 0;
00643    int i = 0;
00644    int z = 0;
00645    int spaceleft = 0;
00646    struct timeval time_start, time_end;
00647 
00648    if (ast_strlen_zero(suffix)) {
00649       ast_log(LOG_WARNING, "ast_get_enum need a suffix parameter now.\n");
00650       return -1;
00651    }
00652 
00653    ast_debug(2, "num='%s', tech='%s', suffix='%s', options='%s', record=%d\n", number, tech, suffix, options, record);
00654 
00655 /*
00656   We don't need that any more, that "n" preceding the number has been replaced by a flag
00657   in the options paramter.
00658    ast_copy_string(naptrinput, number, sizeof(naptrinput));
00659 */
00660 /*
00661  * The "number" parameter includes a leading '+' if it's a full E.164 number (and not ISN)
00662  * We need to preserve that as the regex inside NAPTRs expect the +.
00663  *
00664  * But for the domain generation, the '+' is a nuissance, so we get rid of it.
00665 */
00666    ast_copy_string(naptrinput, number[0] == 'n' ? number + 1 : number, sizeof(naptrinput));
00667    if (number[0] == '+') {
00668       number++;
00669    }
00670 
00671    if (!(context = ast_calloc(1, sizeof(*context)))) {
00672       return -1;
00673    }
00674 
00675    if ((p3 = strchr(naptrinput, '*'))) {
00676       *p3='\0';
00677    }
00678 
00679    context->naptrinput = naptrinput;   /* The number */
00680    context->dst = dst;        /* Return string */
00681    context->dstlen = dstlen;
00682    context->tech = tech;
00683    context->techlen = techlen;
00684    context->options = 0;
00685    context->position = record > 0 ? record : 1;
00686    context->count = 0;
00687    context->naptr_rrs = NULL;
00688    context->naptr_rrs_count = 0;
00689 
00690    /*
00691     * Process options:
00692     *
00693     *    c  Return count, not URI
00694     *    i  Use infrastructure ENUM 
00695     *    s  Do ISN transformation
00696     *    d  Direct DNS query: no reversing.
00697     *
00698     */
00699    if (options != NULL) {
00700       if (strchr(options,'s')) {
00701          context->options |= ENUMLOOKUP_OPTIONS_ISN;
00702       } else if (strchr(options,'i')) {
00703          context->options |= ENUMLOOKUP_OPTIONS_IENUM;
00704       } else if (strchr(options,'d')) {
00705          context->options |= ENUMLOOKUP_OPTIONS_DIRECT;
00706       }
00707       if (strchr(options,'c')) {
00708          context->options |= ENUMLOOKUP_OPTIONS_COUNT;
00709       }
00710       if (strchr(number,'*')) {
00711          context->options |= ENUMLOOKUP_OPTIONS_ISN;
00712       }
00713    }
00714    ast_debug(2, "ENUM options(%s): pos=%d, options='%d'\n", options, context->position, context->options);
00715    ast_debug(1, "n='%s', tech='%s', suffix='%s', options='%d', record='%d'\n",
00716          number, tech, suffix, context->options, context->position);
00717 
00718    /*
00719     * This code does more than simple RFC3261 ENUM. All these rewriting 
00720     * schemes have in common that they build the FQDN for the NAPTR lookup
00721     * by concatenating
00722     *    - a number which needs be flipped and "."-seperated   (left)
00723     *    - some fixed string              (middle)
00724     *    - an Apex.                 (apex)
00725     *
00726     * The RFC3261 ENUM is: left=full number, middle="", apex=from args.
00727     * ISN:  number = "middle*left", apex=from args
00728     * I-ENUM: EBL parameters build the split, can change apex
00729     * Direct: left="", middle=argument, apex=from args
00730     *
00731     */
00732 
00733    /* default: the whole number will be flipped, no middle domain component */
00734    ast_copy_string(left, number, sizeof(left));
00735    middle[0] = '\0';
00736    /*
00737     * I-ENUM can change the apex, thus we copy it 
00738     */
00739    ast_copy_string(apex, suffix, sizeof(apex));
00740    /* ISN rewrite */
00741    if ((context->options & ENUMLOOKUP_OPTIONS_ISN) && (p1 = strchr(number, '*'))) {
00742       *p1++ = '\0';
00743       ast_copy_string(left, number, sizeof(left));
00744       ast_copy_string(middle, p1, sizeof(middle) - 1);
00745       strcat(middle, ".");
00746       ast_debug(2, "ISN ENUM: left=%s, middle='%s'\n", left, middle);
00747    /* Direct DNS lookup rewrite */
00748    } else if (context->options & ENUMLOOKUP_OPTIONS_DIRECT) {
00749       left[0] = 0; /* nothing to flip around */
00750       ast_copy_string(middle, number, sizeof(middle) - 1);
00751       strcat(middle, ".");
00752       ast_debug(2, "DIRECT ENUM:  middle='%s'\n", middle);
00753    /* Infrastructure ENUM rewrite */
00754    } else if (context->options & ENUMLOOKUP_OPTIONS_IENUM) {
00755       int sdl = 0;
00756       char cc[8];
00757       char sep[256], n_apex[256];
00758       int cc_len = cclen(number);
00759       sdl = cc_len;
00760       ast_mutex_lock(&enumlock);
00761       ast_copy_string(sep, ienum_branchlabel, sizeof(sep)); /* default */
00762       ast_mutex_unlock(&enumlock);
00763 
00764       switch (ebl_alg) {
00765       case ENUMLOOKUP_BLR_EBL:
00766          ast_copy_string(cc, number, cc_len); /* cclen() never returns more than 3 */
00767          sdl = blr_ebl(cc, suffix, sep, sizeof(sep) - 1, n_apex, sizeof(n_apex) - 1);
00768 
00769          if (sdl >= 0) {
00770             ast_copy_string(apex, n_apex, sizeof(apex));
00771             ast_debug(2, "EBL ENUM: sep=%s, apex='%s'\n", sep, n_apex);
00772          } else {
00773             sdl = cc_len;
00774          }
00775          break;
00776       case ENUMLOOKUP_BLR_TXT:
00777          ast_copy_string(cc, number, cc_len); /* cclen() never returns more than 3 */
00778          sdl = blr_txt(cc, suffix);
00779 
00780          if (sdl < 0) {
00781             sdl = cc_len;
00782          }
00783          break;
00784 
00785       case ENUMLOOKUP_BLR_CC: /* BLR is at the country-code level */
00786       default:
00787          sdl = cc_len;
00788          break;
00789       }
00790 
00791       if (sdl > strlen(number)) {   /* Number too short for this sdl? */
00792          ast_log(LOG_WARNING, "I-ENUM: subdomain location %d behind number %s\n", sdl, number);
00793          return 0;
00794       }
00795       ast_copy_string(left, number + sdl, sizeof(left));
00796 
00797       ast_mutex_lock(&enumlock);
00798       ast_copy_string(middle, sep, sizeof(middle) - 1);
00799       strcat(middle, ".");
00800       ast_mutex_unlock(&enumlock);
00801 
00802       /* check the space we need for middle */
00803       if ((sdl * 2 + strlen(middle) + 2) > sizeof(middle)) {
00804          ast_log(LOG_WARNING, "ast_get_enum: not enough space for I-ENUM rewrite.\n");
00805          return -1;
00806       }
00807 
00808       p1 = middle + strlen(middle);
00809       for (p2 = (char *) number + sdl - 1; p2 >= number; p2--) {
00810          if (isdigit(*p2)) {
00811             *p1++ = *p2;
00812             *p1++ = '.';
00813          }
00814       }
00815       *p1 = '\0';
00816 
00817       ast_debug(2, "I-ENUM: cclen=%d, left=%s, middle='%s', apex='%s'\n", cc_len, left, middle, apex);
00818    }
00819 
00820    if (strlen(left) * 2 + 2 > sizeof(domain)) {
00821       ast_log(LOG_WARNING, "string to long in ast_get_enum\n");
00822       return -1;
00823    }
00824 
00825    /* flip left into domain */
00826    p1 = domain;
00827    for (p2 = left + strlen(left); p2 >= left; p2--) {
00828       if (isdigit(*p2)) {
00829          *p1++ = *p2;
00830          *p1++ = '.';
00831       }
00832    }
00833    *p1 = '\0';
00834 
00835    if (chan && ast_autoservice_start(chan) < 0) {
00836       ast_free(context);
00837       return -1;
00838    }
00839 
00840    spaceleft = sizeof(tmp) - 2;
00841    ast_copy_string(tmp, domain, spaceleft);
00842    spaceleft -= strlen(domain);
00843 
00844    if (*middle) {
00845       strncat(tmp, middle, spaceleft);
00846       spaceleft -= strlen(middle);
00847    }
00848 
00849    strncat(tmp,apex,spaceleft);
00850    time_start = ast_tvnow();
00851    ret = ast_search_dns(context, tmp, C_IN, T_NAPTR, enum_callback);
00852    time_end = ast_tvnow();
00853 
00854    ast_debug(2, "profiling: %s, %s, %" PRIi64 " ms\n",
00855          (ret == 0) ? "OK" : "FAIL", tmp, ast_tvdiff_ms(time_end, time_start));
00856 
00857    if (ret < 0) {
00858       ast_debug(1, "No such number found: %s (%s)\n", tmp, strerror(errno));
00859       strcpy(dst, "0");
00860       ret = 0;
00861    }
00862 
00863    if (context->naptr_rrs_count >= context->position && ! (context->options & ENUMLOOKUP_OPTIONS_COUNT)) {
00864       /* sort array by NAPTR order/preference */
00865       for (k = 0; k < context->naptr_rrs_count; k++) {
00866          for (i = 0; i < context->naptr_rrs_count; i++) {
00867             /* use order first and then preference to compare */
00868             if ((ntohs(context->naptr_rrs[k].naptr.order) < ntohs(context->naptr_rrs[i].naptr.order)
00869                  && context->naptr_rrs[k].sort_pos > context->naptr_rrs[i].sort_pos)
00870                  || (ntohs(context->naptr_rrs[k].naptr.order) > ntohs(context->naptr_rrs[i].naptr.order)
00871                  && context->naptr_rrs[k].sort_pos < context->naptr_rrs[i].sort_pos)) {
00872                z = context->naptr_rrs[k].sort_pos;
00873                context->naptr_rrs[k].sort_pos = context->naptr_rrs[i].sort_pos;
00874                context->naptr_rrs[i].sort_pos = z;
00875                continue;
00876             }
00877             if (ntohs(context->naptr_rrs[k].naptr.order) == ntohs(context->naptr_rrs[i].naptr.order)) {
00878                if ((ntohs(context->naptr_rrs[k].naptr.pref) < ntohs(context->naptr_rrs[i].naptr.pref)
00879                     && context->naptr_rrs[k].sort_pos > context->naptr_rrs[i].sort_pos)
00880                     || (ntohs(context->naptr_rrs[k].naptr.pref) > ntohs(context->naptr_rrs[i].naptr.pref)
00881                     && context->naptr_rrs[k].sort_pos < context->naptr_rrs[i].sort_pos)) {
00882                   z = context->naptr_rrs[k].sort_pos;
00883                   context->naptr_rrs[k].sort_pos = context->naptr_rrs[i].sort_pos;
00884                   context->naptr_rrs[i].sort_pos = z;
00885                }
00886             }
00887          }
00888       }
00889       for (k = 0; k < context->naptr_rrs_count; k++) {
00890          if (context->naptr_rrs[k].sort_pos == context->position - 1) {
00891             ast_copy_string(context->dst, context->naptr_rrs[k].result, dstlen);
00892             ast_copy_string(context->tech, context->naptr_rrs[k].tech, techlen);
00893             break;
00894          }
00895       }
00896    } else if (!(context->options & ENUMLOOKUP_OPTIONS_COUNT)) {
00897       context->dst[0] = 0;
00898    } else if ((context->options & ENUMLOOKUP_OPTIONS_COUNT)) {
00899       snprintf(context->dst, context->dstlen, "%d", context->count);
00900    }
00901 
00902    if (chan) {
00903       ret |= ast_autoservice_stop(chan);
00904    }
00905 
00906    if (!argcontext) {
00907       for (k = 0; k < context->naptr_rrs_count; k++) {
00908          ast_free(context->naptr_rrs[k].result);
00909          ast_free(context->naptr_rrs[k].tech);
00910       }
00911       ast_free(context->naptr_rrs);
00912       ast_free(context);
00913    } else {
00914       *argcontext = context;
00915    }
00916 
00917    return ret;
00918 }

int ast_get_txt ( struct ast_channel chan,
const char *  number,
char *  txt,
int  maxtxt,
char *  suffix 
)

Lookup DNS TXT record (used by app TXTCIDnum).

Really has nothing to do with enum, but anyway... Actually, there is now an internet-draft which describes how callerID should be stored in ENUM domains: draft-ietf-enum-cnam-04.txt The algorithm implemented here will thus be obsolete soon.

Parameters:
chan Channel
number E164 number with or without the leading +
txt Text string (return value)
maxtxt Max length of "txt"
suffix Zone suffix
Version:
1.6.1 new suffix parameter to take into account caller ids that aren't in e164.arpa

1.6.1 removed parameters location, maxloc, technology, maxtech as all the information is stored the txt string

Definition at line 920 of file enum.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_debug, context, and errno.

Referenced by function_txtcidname().

00921 {
00922    struct txt_context context;
00923    char tmp[259 + 512];
00924    int pos = strlen(number) - 1;
00925    int newpos = 0;
00926    int ret = -1;
00927 
00928    ast_debug(4, "ast_get_txt: Number = '%s', suffix = '%s'\n", number, suffix);
00929 
00930    if (chan && ast_autoservice_start(chan) < 0) {
00931       return -1;
00932    }
00933  
00934    if (pos > 128) {
00935       pos = 128;
00936    }
00937 
00938    while (pos >= 0) {
00939       if (isdigit(number[pos])) {
00940          tmp[newpos++] = number[pos];
00941          tmp[newpos++] = '.';
00942       }
00943       pos--;
00944    }
00945 
00946    ast_copy_string(&tmp[newpos], suffix, sizeof(tmp) - newpos);
00947 
00948    if (ret < 0) {
00949       ast_debug(2, "No such number found in ENUM: %s (%s)\n", tmp, strerror(errno));
00950       ret = 0;
00951    } else {
00952       ast_copy_string(txt, context.txt, txtlen);
00953    }
00954    if (chan) {
00955       ret |= ast_autoservice_stop(chan);
00956    }
00957    return ret;
00958 }


Generated on Sat Mar 10 01:55:21 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7