enum.h File Reference

DNS and ENUM functions. More...

#include "asterisk/channel.h"

Include dependency graph for enum.h:

This graph shows which files directly or indirectly include this file:

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

References private_enum_init().

Referenced by main().

01014 {
01015    return private_enum_init(0);
01016 }

int ast_enum_reload ( void   ) 

Definition at line 1018 of file enum.c.

References private_enum_init().

01019 {
01020    return private_enum_init(1);
01021 }

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

References ast_autoservice_start(), ast_autoservice_stop(), 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_context::count, enum_context::dst, enum_context::dstlen, 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, enum_naptr_rr::naptr, enum_context::naptr_rrs, enum_context::naptr_rrs_count, enum_context::naptrinput, NULL, enum_context::options, naptr::order, enum_context::position, naptr::pref, enum_naptr_rr::result, enum_naptr_rr::sort_pos, enum_naptr_rr::tech, enum_context::tech, enum_context::techlen, and tmp().

Referenced by enum_query_read(), and function_enum().

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

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

References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_debug, errno, tmp(), and txt_context::txt.

Referenced by function_txtcidname().

00936 {
00937    struct txt_context context;
00938    char tmp[259 + 512];
00939    int pos = strlen(number) - 1;
00940    int newpos = 0;
00941    int ret = -1;
00942 
00943    ast_debug(4, "ast_get_txt: Number = '%s', suffix = '%s'\n", number, suffix);
00944 
00945    if (chan && ast_autoservice_start(chan) < 0) {
00946       return -1;
00947    }
00948 
00949    if (pos > 128) {
00950       pos = 128;
00951    }
00952 
00953    while (pos >= 0) {
00954       if (isdigit(number[pos])) {
00955          tmp[newpos++] = number[pos];
00956          tmp[newpos++] = '.';
00957       }
00958       pos--;
00959    }
00960 
00961    ast_copy_string(&tmp[newpos], suffix, sizeof(tmp) - newpos);
00962 
00963    if (ret < 0) {
00964       ast_debug(2, "No such number found in ENUM: %s (%s)\n", tmp, strerror(errno));
00965       ret = 0;
00966    } else {
00967       ast_copy_string(txt, context.txt, txtlen);
00968    }
00969    if (chan) {
00970       ret |= ast_autoservice_stop(chan);
00971    }
00972    return ret;
00973 }


Generated on Thu Apr 16 06:30:52 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6