#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"
Go to the source code of this file.
Data Structures | |
struct | ebl_context |
struct | txt_context |
Defines | |
#define | ENUMLOOKUP_BLR_CC 0 |
#define | ENUMLOOKUP_BLR_EBL 2 |
#define | ENUMLOOKUP_BLR_TXT 1 |
#define | ENUMLOOKUP_OPTIONS_COUNT 1 |
#define | ENUMLOOKUP_OPTIONS_DIRECT 8 |
#define | ENUMLOOKUP_OPTIONS_IENUM 4 |
#define | ENUMLOOKUP_OPTIONS_ISN 2 |
#define | T_EBL 65300 |
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 *txt, int txtlen, char *suffix) |
Lookup DNS TXT record (used by app TXTCIDnum). | |
static int | blr_ebl (const char *cc, const char *suffix, char *separator, int sep_len, char *apex, int apex_len) |
Evaluate the I-ENUM branch as stored in an EBL record. | |
static int | blr_txt (const char *cc, const char *suffix) |
Determine the branch location record as stored in a TXT record. | |
static int | cclen (const char *number) |
Determine the length of a country code when given an E.164 string. | |
static int | ebl_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer) |
Callback for EBL record lookup. | |
static int | enum_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer) |
Callback from ENUM lookup function. | |
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 (unsigned char *dst, int dstsize, char *tech, int techsize, unsigned char *answer, int len, unsigned 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, /ol version. | |
Variables | |
static int | ebl_alg = ENUMLOOKUP_BLR_CC |
static ast_mutex_t | enumlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static char | ienum_branchlabel [32] = "i" |
The service type selection needs to be redone.
Definition in file enum.c.
#define ENUMLOOKUP_BLR_CC 0 |
#define ENUMLOOKUP_BLR_EBL 2 |
#define ENUMLOOKUP_BLR_TXT 1 |
#define ENUMLOOKUP_OPTIONS_COUNT 1 |
#define ENUMLOOKUP_OPTIONS_DIRECT 8 |
#define ENUMLOOKUP_OPTIONS_IENUM 4 |
#define ENUMLOOKUP_OPTIONS_ISN 2 |
int ast_enum_init | ( | void | ) |
Definition at line 1006 of file enum.c.
References private_enum_init().
Referenced by main().
01007 { 01008 return private_enum_init(0); 01009 }
int ast_enum_reload | ( | void | ) |
Definition at line 1011 of file enum.c.
References private_enum_init().
01012 { 01013 return private_enum_init(1); 01014 }
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.
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) |
1 | if found | |
0 | if not found | |
-1 | on hangup |
Definition at line 632 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().
00633 { 00634 struct enum_context *context; 00635 char tmp[512]; 00636 char domain[256]; 00637 char left[128]; 00638 char middle[128]; 00639 char naptrinput[128]; 00640 char apex[128] = ""; 00641 int ret = -1; 00642 /* for ISN rewrite */ 00643 char *p1 = NULL; 00644 char *p2 = NULL; 00645 char *p3 = NULL; 00646 int k = 0; 00647 int i = 0; 00648 int z = 0; 00649 int spaceleft = 0; 00650 struct timeval time_start, time_end; 00651 00652 if (ast_strlen_zero(suffix)) { 00653 ast_log(LOG_WARNING, "ast_get_enum need a suffix parameter now.\n"); 00654 return -1; 00655 } 00656 00657 ast_debug(2, "num='%s', tech='%s', suffix='%s', options='%s', record=%d\n", number, tech, suffix, options, record); 00658 00659 /* 00660 We don't need that any more, that "n" preceding the number has been replaced by a flag 00661 in the options paramter. 00662 ast_copy_string(naptrinput, number, sizeof(naptrinput)); 00663 */ 00664 /* 00665 * The "number" parameter includes a leading '+' if it's a full E.164 number (and not ISN) 00666 * We need to preserve that as the regex inside NAPTRs expect the +. 00667 * 00668 * But for the domain generation, the '+' is a nuissance, so we get rid of it. 00669 */ 00670 ast_copy_string(naptrinput, number[0] == 'n' ? number + 1 : number, sizeof(naptrinput)); 00671 if (number[0] == '+') { 00672 number++; 00673 } 00674 00675 if (!(context = ast_calloc(1, sizeof(*context)))) { 00676 return -1; 00677 } 00678 00679 if ((p3 = strchr(naptrinput, '*'))) { 00680 *p3='\0'; 00681 } 00682 00683 context->naptrinput = naptrinput; /* The number */ 00684 context->dst = dst; /* Return string */ 00685 context->dstlen = dstlen; 00686 context->tech = tech; 00687 context->techlen = techlen; 00688 context->options = 0; 00689 context->position = record > 0 ? record : 1; 00690 context->count = 0; 00691 context->naptr_rrs = NULL; 00692 context->naptr_rrs_count = 0; 00693 00694 /* 00695 * Process options: 00696 * 00697 * c Return count, not URI 00698 * i Use infrastructure ENUM 00699 * s Do ISN transformation 00700 * d Direct DNS query: no reversing. 00701 * 00702 */ 00703 if (options != NULL) { 00704 if (strchr(options,'s')) { 00705 context->options |= ENUMLOOKUP_OPTIONS_ISN; 00706 } else if (strchr(options,'i')) { 00707 context->options |= ENUMLOOKUP_OPTIONS_IENUM; 00708 } else if (strchr(options,'d')) { 00709 context->options |= ENUMLOOKUP_OPTIONS_DIRECT; 00710 } 00711 if (strchr(options,'c')) { 00712 context->options |= ENUMLOOKUP_OPTIONS_COUNT; 00713 } 00714 if (strchr(number,'*')) { 00715 context->options |= ENUMLOOKUP_OPTIONS_ISN; 00716 } 00717 } 00718 ast_debug(2, "ENUM options(%s): pos=%d, options='%d'\n", options, context->position, context->options); 00719 ast_debug(1, "n='%s', tech='%s', suffix='%s', options='%d', record='%d'\n", 00720 number, tech, suffix, context->options, context->position); 00721 00722 /* 00723 * This code does more than simple RFC3261 ENUM. All these rewriting 00724 * schemes have in common that they build the FQDN for the NAPTR lookup 00725 * by concatenating 00726 * - a number which needs be flipped and "."-seperated (left) 00727 * - some fixed string (middle) 00728 * - an Apex. (apex) 00729 * 00730 * The RFC3261 ENUM is: left=full number, middle="", apex=from args. 00731 * ISN: number = "middle*left", apex=from args 00732 * I-ENUM: EBL parameters build the split, can change apex 00733 * Direct: left="", middle=argument, apex=from args 00734 * 00735 */ 00736 00737 /* default: the whole number will be flipped, no middle domain component */ 00738 ast_copy_string(left, number, sizeof(left)); 00739 middle[0] = '\0'; 00740 /* 00741 * I-ENUM can change the apex, thus we copy it 00742 */ 00743 ast_copy_string(apex, suffix, sizeof(apex)); 00744 /* ISN rewrite */ 00745 if ((context->options & ENUMLOOKUP_OPTIONS_ISN) && (p1 = strchr(number, '*'))) { 00746 *p1++ = '\0'; 00747 ast_copy_string(left, number, sizeof(left)); 00748 ast_copy_string(middle, p1, sizeof(middle) - 1); 00749 strcat(middle, "."); 00750 ast_debug(2, "ISN ENUM: left=%s, middle='%s'\n", left, middle); 00751 /* Direct DNS lookup rewrite */ 00752 } else if (context->options & ENUMLOOKUP_OPTIONS_DIRECT) { 00753 left[0] = 0; /* nothing to flip around */ 00754 ast_copy_string(middle, number, sizeof(middle) - 1); 00755 strcat(middle, "."); 00756 ast_debug(2, "DIRECT ENUM: middle='%s'\n", middle); 00757 /* Infrastructure ENUM rewrite */ 00758 } else if (context->options & ENUMLOOKUP_OPTIONS_IENUM) { 00759 int sdl = 0; 00760 char cc[8]; 00761 char sep[256], n_apex[256]; 00762 int cc_len = cclen(number); 00763 sdl = cc_len; 00764 ast_mutex_lock(&enumlock); 00765 ast_copy_string(sep, ienum_branchlabel, sizeof(sep)); /* default */ 00766 ast_mutex_unlock(&enumlock); 00767 00768 switch (ebl_alg) { 00769 case ENUMLOOKUP_BLR_EBL: 00770 ast_copy_string(cc, number, cc_len); /* cclen() never returns more than 3 */ 00771 sdl = blr_ebl(cc, suffix, sep, sizeof(sep) - 1, n_apex, sizeof(n_apex) - 1); 00772 00773 if (sdl >= 0) { 00774 ast_copy_string(apex, n_apex, sizeof(apex)); 00775 ast_debug(2, "EBL ENUM: sep=%s, apex='%s'\n", sep, n_apex); 00776 } else { 00777 sdl = cc_len; 00778 } 00779 break; 00780 case ENUMLOOKUP_BLR_TXT: 00781 ast_copy_string(cc, number, cc_len); /* cclen() never returns more than 3 */ 00782 sdl = blr_txt(cc, suffix); 00783 00784 if (sdl < 0) { 00785 sdl = cc_len; 00786 } 00787 break; 00788 00789 case ENUMLOOKUP_BLR_CC: /* BLR is at the country-code level */ 00790 default: 00791 sdl = cc_len; 00792 break; 00793 } 00794 00795 if (sdl > strlen(number)) { /* Number too short for this sdl? */ 00796 ast_log(LOG_WARNING, "I-ENUM: subdomain location %d behind number %s\n", sdl, number); 00797 ast_free(context); 00798 return 0; 00799 } 00800 ast_copy_string(left, number + sdl, sizeof(left)); 00801 00802 ast_mutex_lock(&enumlock); 00803 ast_copy_string(middle, sep, sizeof(middle) - 1); 00804 strcat(middle, "."); 00805 ast_mutex_unlock(&enumlock); 00806 00807 /* check the space we need for middle */ 00808 if ((sdl * 2 + strlen(middle) + 2) > sizeof(middle)) { 00809 ast_log(LOG_WARNING, "ast_get_enum: not enough space for I-ENUM rewrite.\n"); 00810 ast_free(context); 00811 return -1; 00812 } 00813 00814 p1 = middle + strlen(middle); 00815 for (p2 = (char *) number + sdl - 1; p2 >= number; p2--) { 00816 if (isdigit(*p2)) { 00817 *p1++ = *p2; 00818 *p1++ = '.'; 00819 } 00820 } 00821 *p1 = '\0'; 00822 00823 ast_debug(2, "I-ENUM: cclen=%d, left=%s, middle='%s', apex='%s'\n", cc_len, left, middle, apex); 00824 } 00825 00826 if (strlen(left) * 2 + 2 > sizeof(domain)) { 00827 ast_log(LOG_WARNING, "string to long in ast_get_enum\n"); 00828 ast_free(context); 00829 return -1; 00830 } 00831 00832 /* flip left into domain */ 00833 p1 = domain; 00834 for (p2 = left + strlen(left); p2 >= left; p2--) { 00835 if (isdigit(*p2)) { 00836 *p1++ = *p2; 00837 *p1++ = '.'; 00838 } 00839 } 00840 *p1 = '\0'; 00841 00842 if (chan && ast_autoservice_start(chan) < 0) { 00843 ast_free(context); 00844 return -1; 00845 } 00846 00847 spaceleft = sizeof(tmp) - 2; 00848 ast_copy_string(tmp, domain, spaceleft); 00849 spaceleft -= strlen(domain); 00850 00851 if (*middle) { 00852 strncat(tmp, middle, spaceleft); 00853 spaceleft -= strlen(middle); 00854 } 00855 00856 strncat(tmp,apex,spaceleft); 00857 time_start = ast_tvnow(); 00858 ret = ast_search_dns(context, tmp, C_IN, T_NAPTR, enum_callback); 00859 time_end = ast_tvnow(); 00860 00861 ast_debug(2, "profiling: %s, %s, %" PRIi64 " ms\n", 00862 (ret == 0) ? "OK" : "FAIL", tmp, ast_tvdiff_ms(time_end, time_start)); 00863 00864 if (ret < 0) { 00865 ast_debug(1, "No such number found: %s (%s)\n", tmp, strerror(errno)); 00866 strcpy(dst, "0"); 00867 ret = 0; 00868 } 00869 00870 if (context->naptr_rrs_count >= context->position && ! (context->options & ENUMLOOKUP_OPTIONS_COUNT)) { 00871 /* sort array by NAPTR order/preference */ 00872 for (k = 0; k < context->naptr_rrs_count; k++) { 00873 for (i = 0; i < context->naptr_rrs_count; i++) { 00874 /* use order first and then preference to compare */ 00875 if ((ntohs(context->naptr_rrs[k].naptr.order) < ntohs(context->naptr_rrs[i].naptr.order) 00876 && context->naptr_rrs[k].sort_pos > context->naptr_rrs[i].sort_pos) 00877 || (ntohs(context->naptr_rrs[k].naptr.order) > ntohs(context->naptr_rrs[i].naptr.order) 00878 && context->naptr_rrs[k].sort_pos < context->naptr_rrs[i].sort_pos)) { 00879 z = context->naptr_rrs[k].sort_pos; 00880 context->naptr_rrs[k].sort_pos = context->naptr_rrs[i].sort_pos; 00881 context->naptr_rrs[i].sort_pos = z; 00882 continue; 00883 } 00884 if (ntohs(context->naptr_rrs[k].naptr.order) == ntohs(context->naptr_rrs[i].naptr.order)) { 00885 if ((ntohs(context->naptr_rrs[k].naptr.pref) < ntohs(context->naptr_rrs[i].naptr.pref) 00886 && context->naptr_rrs[k].sort_pos > context->naptr_rrs[i].sort_pos) 00887 || (ntohs(context->naptr_rrs[k].naptr.pref) > ntohs(context->naptr_rrs[i].naptr.pref) 00888 && context->naptr_rrs[k].sort_pos < context->naptr_rrs[i].sort_pos)) { 00889 z = context->naptr_rrs[k].sort_pos; 00890 context->naptr_rrs[k].sort_pos = context->naptr_rrs[i].sort_pos; 00891 context->naptr_rrs[i].sort_pos = z; 00892 } 00893 } 00894 } 00895 } 00896 for (k = 0; k < context->naptr_rrs_count; k++) { 00897 if (context->naptr_rrs[k].sort_pos == context->position - 1) { 00898 ast_copy_string(context->dst, context->naptr_rrs[k].result, dstlen); 00899 ast_copy_string(context->tech, context->naptr_rrs[k].tech, techlen); 00900 break; 00901 } 00902 } 00903 } else if (!(context->options & ENUMLOOKUP_OPTIONS_COUNT)) { 00904 context->dst[0] = 0; 00905 } else if ((context->options & ENUMLOOKUP_OPTIONS_COUNT)) { 00906 snprintf(context->dst, context->dstlen, "%d", context->count); 00907 } 00908 00909 if (chan) { 00910 ret |= ast_autoservice_stop(chan); 00911 } 00912 00913 if (!argcontext) { 00914 for (k = 0; k < context->naptr_rrs_count; k++) { 00915 ast_free(context->naptr_rrs[k].result); 00916 ast_free(context->naptr_rrs[k].tech); 00917 } 00918 ast_free(context->naptr_rrs); 00919 ast_free(context); 00920 } else { 00921 *argcontext = context; 00922 } 00923 00924 return ret; 00925 }
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.
chan | Channel | |
number | E164 number with or without the leading + | |
txt | Text string (return value) | |
maxtxt | Max length of "txt" | |
suffix | Zone suffix |
1.6.1 removed parameters location, maxloc, technology, maxtech as all the information is stored the txt string
Definition at line 927 of file enum.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_debug, context, and errno.
Referenced by function_txtcidname().
00928 { 00929 struct txt_context context; 00930 char tmp[259 + 512]; 00931 int pos = strlen(number) - 1; 00932 int newpos = 0; 00933 int ret = -1; 00934 00935 ast_debug(4, "ast_get_txt: Number = '%s', suffix = '%s'\n", number, suffix); 00936 00937 if (chan && ast_autoservice_start(chan) < 0) { 00938 return -1; 00939 } 00940 00941 if (pos > 128) { 00942 pos = 128; 00943 } 00944 00945 while (pos >= 0) { 00946 if (isdigit(number[pos])) { 00947 tmp[newpos++] = number[pos]; 00948 tmp[newpos++] = '.'; 00949 } 00950 pos--; 00951 } 00952 00953 ast_copy_string(&tmp[newpos], suffix, sizeof(tmp) - newpos); 00954 00955 if (ret < 0) { 00956 ast_debug(2, "No such number found in ENUM: %s (%s)\n", tmp, strerror(errno)); 00957 ret = 0; 00958 } else { 00959 ast_copy_string(txt, context.txt, txtlen); 00960 } 00961 if (chan) { 00962 ret |= ast_autoservice_stop(chan); 00963 } 00964 return ret; 00965 }
static int blr_ebl | ( | const char * | cc, | |
const char * | suffix, | |||
char * | separator, | |||
int | sep_len, | |||
char * | apex, | |||
int | apex_len | |||
) | [static] |
Evaluate the I-ENUM branch as stored in an EBL record.
Definition at line 324 of file enum.c.
References ast_copy_string(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_search_dns(), ast_verb, context, ebl_callback(), enumlock, LOG_WARNING, and T_EBL.
Referenced by ast_get_enum().
00325 { 00326 struct ebl_context context; 00327 char domain[128] = ""; 00328 char *p1,*p2; 00329 int ret; 00330 00331 ast_mutex_lock(&enumlock); 00332 00333 ast_verb(4, "blr_ebl() cc='%s', suffix='%s', c_bl='%s'\n", cc, suffix, ienum_branchlabel); 00334 00335 if (sizeof(domain) < (strlen(cc) * 2 + strlen(ienum_branchlabel) + strlen(suffix) + 2)) { 00336 ast_mutex_unlock(&enumlock); 00337 ast_log(LOG_WARNING, "ERROR: string sizing in blr_EBL.\n"); 00338 return -1; 00339 } 00340 00341 p1 = domain + snprintf(domain, sizeof(domain), "%s.", ienum_branchlabel); 00342 ast_mutex_unlock(&enumlock); 00343 00344 for (p2 = (char *) cc + strlen(cc) - 1; p2 >= cc; p2--) { 00345 if (isdigit(*p2)) { 00346 *p1++ = *p2; 00347 *p1++ = '.'; 00348 } 00349 } 00350 strcat(p1, suffix); 00351 00352 ast_verb(4, "blr_ebl() FQDN for EBL record: %s, cc was %s\n", domain, cc); 00353 00354 ret = ast_search_dns(&context, domain, C_IN, T_EBL, ebl_callback); 00355 if (ret > 0) { 00356 ret = context.pos; 00357 00358 if ((ret >= 0) && (ret < 20)) { 00359 ast_verb(3, "blr_txt() BLR EBL record for %s is %d/%s/%s)\n", cc, ret, context.separator, context.apex); 00360 ast_copy_string(separator, context.separator, sep_len); 00361 ast_copy_string(apex, context.apex, apex_len); 00362 return ret; 00363 } 00364 } 00365 ast_verb(3, "blr_txt() BLR EBL record for %s not found (apex: %s)\n", cc, suffix); 00366 return -1; 00367 }
static int blr_txt | ( | const char * | cc, | |
const char * | suffix | |||
) | [static] |
Determine the branch location record as stored in a TXT record.
Definition at line 195 of file enum.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_search_dns(), ast_verb, context, enumlock, LOG_WARNING, and txt_callback().
Referenced by ast_get_enum().
00196 { 00197 struct txt_context context; 00198 char domain[128] = ""; 00199 char *p1, *p2; 00200 int ret; 00201 00202 ast_mutex_lock(&enumlock); 00203 00204 ast_verb(4, "blr_txt() cc='%s', suffix='%s', c_bl='%s'\n", cc, suffix, ienum_branchlabel); 00205 00206 if (sizeof(domain) < (strlen(cc) * 2 + strlen(ienum_branchlabel) + strlen(suffix) + 2)) { 00207 ast_mutex_unlock(&enumlock); 00208 ast_log(LOG_WARNING, "ERROR: string sizing in blr_txt.\n"); 00209 return -1; 00210 } 00211 00212 p1 = domain + snprintf(domain, sizeof(domain), "%s.", ienum_branchlabel); 00213 ast_mutex_unlock(&enumlock); 00214 00215 for (p2 = (char *) cc + strlen(cc) - 1; p2 >= cc; p2--) { 00216 if (isdigit(*p2)) { 00217 *p1++ = *p2; 00218 *p1++ = '.'; 00219 } 00220 } 00221 strcat(p1, suffix); 00222 00223 ast_verb(4, "blr_txt() FQDN for TXT record: %s, cc was %s\n", domain, cc); 00224 00225 ret = ast_search_dns(&context, domain, C_IN, T_TXT, txt_callback); 00226 00227 if (ret > 0) { 00228 ret = atoi(context.txt); 00229 00230 if ((ret >= 0) && (ret < 20)) { 00231 ast_verb(3, "blr_txt() BLR TXT record for %s is %d (apex: %s)\n", cc, ret, suffix); 00232 return ret; 00233 } 00234 } 00235 00236 ast_verb(3, "blr_txt() BLR TXT record for %s not found (apex: %s)\n", cc, suffix); 00237 00238 return -1; 00239 }
static int cclen | ( | const char * | number | ) | [static] |
Determine the length of a country code when given an E.164 string.
Definition at line 110 of file enum.c.
Referenced by ast_get_enum().
00111 { 00112 int cc; 00113 char digits[3] = ""; 00114 00115 if (!number || (strlen(number) < 3)) { 00116 return 0; 00117 } 00118 00119 strncpy(digits, number, 2); 00120 00121 if (!sscanf(digits, "%30d", &cc)) { 00122 return 0; 00123 } 00124 00125 if (cc / 10 == 1 || cc / 10 == 7) 00126 return 1; 00127 00128 if (cc == 20 || cc == 27 || (cc >= 30 && cc <= 34) || cc == 36 || 00129 cc == 39 || cc == 40 || cc == 41 || (cc >= 40 && cc <= 41) || 00130 (cc >= 43 && cc <= 49) || (cc >= 51 && cc <= 58) || 00131 (cc >= 60 && cc <= 66) || cc == 81 || cc == 82 || cc == 84 || 00132 cc == 86 || (cc >= 90 && cc <= 95) || cc == 98) { 00133 return 2; 00134 } 00135 00136 return 3; 00137 }
static int ebl_callback | ( | void * | context, | |
unsigned char * | answer, | |||
int | len, | |||
unsigned char * | fullanswer | |||
) | [static] |
Callback for EBL record lookup.
Definition at line 250 of file enum.c.
References ebl_context::apex, ebl_context::apex_len, ast_copy_string(), ast_log(), LOG_WARNING, ebl_context::pos, ebl_context::sep_len, and ebl_context::separator.
Referenced by blr_ebl().
00251 { 00252 struct ebl_context *c = context; 00253 unsigned int i; 00254 00255 c->pos = 0; /* default to empty */ 00256 c->separator[0] = 0; 00257 c->sep_len = 0; 00258 c->apex[0] = 0; 00259 c->apex_len = 0; 00260 00261 if (answer == NULL) { 00262 return 0; 00263 } 00264 00265 /* draft-lendl-enum-branch-location-record-00 00266 * 00267 * 0 1 2 3 4 5 6 7 00268 * +--+--+--+--+--+--+--+--+ 00269 * | POSITION | 00270 * +--+--+--+--+--+--+--+--+ 00271 * / SEPARATOR / 00272 * +--+--+--+--+--+--+--+--+ 00273 * / APEX / 00274 * +--+--+--+--+--+--+--+--+ 00275 * 00276 * where POSITION is a single byte, SEPARATOR is a <character-string> 00277 * and APEX is a <domain-name>. 00278 * 00279 */ 00280 00281 c->pos = *answer++; 00282 len -= 1; 00283 00284 if ((c->pos > 15) || len < 2) { /* illegal packet */ 00285 ast_log(LOG_WARNING, "ebl_callback: malformed EBL record.\n"); 00286 return 0; 00287 } 00288 00289 i = *answer++; 00290 len -= 1; 00291 if (i > len) { /* illegal packet */ 00292 ast_log(LOG_WARNING, "ebl_callback: malformed EBL record.\n"); 00293 return 0; 00294 } 00295 00296 ast_copy_string(c->separator, (char *)answer, i + 1); 00297 c->sep_len = i; 00298 00299 answer += i; 00300 len -= i; 00301 00302 if ((i = dn_expand((unsigned char *)fullanswer, (unsigned char *)answer + len, 00303 (unsigned char *)answer, c->apex, sizeof(c->apex) - 1)) < 0) { 00304 ast_log(LOG_WARNING, "Failed to expand hostname\n"); 00305 return 0; 00306 } 00307 c->apex[i] = 0; 00308 c->apex_len = i; 00309 00310 return 1; 00311 }
static int enum_callback | ( | void * | context, | |
unsigned char * | answer, | |||
int | len, | |||
unsigned char * | fullanswer | |||
) | [static] |
Callback from ENUM lookup function.
Definition at line 599 of file enum.c.
References ast_log(), ast_realloc, ast_strdup, ast_strlen_zero(), enum_context::count, 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_naptr_rr::result, enum_naptr_rr::sort_pos, enum_naptr_rr::tech, enum_context::tech, and enum_context::techlen.
Referenced by ast_get_enum().
00600 { 00601 struct enum_context *c = context; 00602 void *p = NULL; 00603 int res; 00604 00605 res = parse_naptr((unsigned char *)c->dst, c->dstlen, c->tech, c->techlen, answer, len, (unsigned char *)c->naptrinput); 00606 00607 if (res < 0) { 00608 ast_log(LOG_WARNING, "Failed to parse naptr\n"); 00609 return -1; 00610 } else if ((res == 0) && !ast_strlen_zero(c->dst)) { /* ok, we got needed NAPTR */ 00611 if (c->options & ENUMLOOKUP_OPTIONS_COUNT) { /* counting RRs */ 00612 c->count++; 00613 snprintf(c->dst, c->dstlen, "%d", c->count); 00614 } else { 00615 if ((p = ast_realloc(c->naptr_rrs, sizeof(*c->naptr_rrs) * (c->naptr_rrs_count + 1)))) { 00616 c->naptr_rrs = p; 00617 memcpy(&c->naptr_rrs[c->naptr_rrs_count].naptr, answer, sizeof(c->naptr_rrs->naptr)); 00618 c->naptr_rrs[c->naptr_rrs_count].result = ast_strdup(c->dst); 00619 c->naptr_rrs[c->naptr_rrs_count].tech = ast_strdup(c->tech); 00620 c->naptr_rrs[c->naptr_rrs_count].sort_pos = c->naptr_rrs_count; 00621 c->naptr_rrs_count++; 00622 } 00623 c->dst[0] = 0; 00624 } 00625 return 0; 00626 } 00627 00628 return 0; 00629 }
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 370 of file enum.c.
References ast_log(), len(), and LOG_WARNING.
Referenced by parse_naptr().
00371 { 00372 unsigned int len, olen; 00373 00374 len = olen = (unsigned int) src[0]; 00375 src++; 00376 srclen--; 00377 00378 if (len > srclen) { 00379 ast_log(LOG_WARNING, "ENUM parsing failed: Wanted %d characters, got %d\n", len, srclen); 00380 return -1; 00381 } 00382 00383 if (len > maxdatalen) 00384 len = maxdatalen; 00385 memcpy(data, src, len); 00386 00387 return olen + 1; 00388 }
static int parse_naptr | ( | unsigned char * | dst, | |
int | dstsize, | |||
char * | tech, | |||
int | techsize, | |||
unsigned char * | answer, | |||
int | len, | |||
unsigned char * | naptrinput | |||
) | [static] |
Parse DNS NAPTR record used in ENUM ---.
Definition at line 391 of file enum.c.
References ARRAY_LEN, ast_copy_string(), ast_debug, ast_log(), LOG_WARNING, and parse_ie().
Referenced by enum_callback().
00392 { 00393 char tech_return[80]; 00394 char *oanswer = (char *)answer; 00395 char flags[512] = ""; 00396 char services[512] = ""; 00397 char *p; 00398 char regexp[512] = ""; 00399 char repl[512] = ""; 00400 char tempdst[512] = ""; 00401 char errbuff[512] = ""; 00402 char delim; 00403 char *delim2; 00404 char *pattern, *subst, *d; 00405 int res; 00406 int regexp_len, rc; 00407 static const int max_bt = 10; /* max num of regexp backreference allowed, must remain 10 to guarantee a valid backreference index */ 00408 int size, matchindex; /* size is the size of the backreference sub. */ 00409 size_t d_len = sizeof(tempdst) - 1; 00410 regex_t preg; 00411 regmatch_t pmatch[max_bt]; 00412 00413 tech_return[0] = '\0'; 00414 dst[0] = '\0'; 00415 00416 if (len < sizeof(struct naptr)) { 00417 ast_log(LOG_WARNING, "NAPTR record length too short\n"); 00418 return -1; 00419 } 00420 answer += sizeof(struct naptr); 00421 len -= sizeof(struct naptr); 00422 if ((res = parse_ie(flags, sizeof(flags) - 1, answer, len)) < 0) { 00423 ast_log(LOG_WARNING, "Failed to get flags from NAPTR record\n"); 00424 return -1; 00425 } else { 00426 answer += res; 00427 len -= res; 00428 } 00429 00430 if ((res = parse_ie(services, sizeof(services) - 1, answer, len)) < 0) { 00431 ast_log(LOG_WARNING, "Failed to get services from NAPTR record\n"); 00432 return -1; 00433 } else { 00434 answer += res; 00435 len -= res; 00436 } 00437 if ((res = parse_ie(regexp, sizeof(regexp) - 1, answer, len)) < 0) { 00438 ast_log(LOG_WARNING, "Failed to get regexp from NAPTR record\n"); 00439 return -1; 00440 } else { 00441 answer += res; 00442 len -= res; 00443 } 00444 00445 if ((res = dn_expand((unsigned char *)oanswer, (unsigned char *)answer + len, (unsigned char *)answer, repl, sizeof(repl) - 1)) < 0) { 00446 ast_log(LOG_WARNING, "Failed to expand hostname\n"); 00447 return -1; 00448 } 00449 00450 ast_debug(3, "NAPTR input='%s', flags='%s', services='%s', regexp='%s', repl='%s'\n", 00451 naptrinput, flags, services, regexp, repl); 00452 00453 00454 if (tolower(flags[0]) != 'u') { 00455 ast_log(LOG_WARNING, "NAPTR Flag must be 'U' or 'u'.\n"); 00456 return -1; 00457 } 00458 00459 p = strstr(services, "e2u+"); 00460 if (p == NULL) 00461 p = strstr(services, "E2U+"); 00462 if (p){ 00463 p = p + 4; 00464 if (strchr(p, ':')){ 00465 p = strchr(p, ':') + 1; 00466 } 00467 ast_copy_string(tech_return, p, sizeof(tech_return)); 00468 } else { 00469 00470 p = strstr(services, "+e2u"); 00471 if (p == NULL) 00472 p = strstr(services, "+E2U"); 00473 if (p) { 00474 *p = 0; 00475 p = strchr(services, ':'); 00476 if (p) 00477 *p = 0; 00478 ast_copy_string(tech_return, services, sizeof(tech_return)); 00479 } 00480 } 00481 00482 regexp_len = strlen(regexp); 00483 if (regexp_len < 7) { 00484 ast_log(LOG_WARNING, "Regex too short to be meaningful.\n"); 00485 return -1; 00486 } 00487 00488 /* this takes the first character of the regexp (which is a delimiter) 00489 * and uses that character to find the index of the second delimiter */ 00490 delim = regexp[0]; 00491 delim2 = strchr(regexp + 1, delim); 00492 if ((delim2 == NULL) || (regexp[regexp_len - 1] != delim)) { /* is the second delimiter found, and is the end of the regexp a delimiter */ 00493 ast_log(LOG_WARNING, "Regex delimiter error (on \"%s\").\n", regexp); 00494 return -1; 00495 } 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 */ 00496 ast_log(LOG_WARNING, "Regex delimiter error (on \"%s\").\n", regexp); 00497 return -1; 00498 } 00499 pattern = regexp + 1; /* pattern is the regex without the begining and ending delimiter */ 00500 *delim2 = 0; /* zero out the middle delimiter */ 00501 subst = delim2 + 1; /* dst substring is everything after the second delimiter. */ 00502 regexp[regexp_len - 1] = 0; /* zero out the last delimiter */ 00503 00504 /* 00505 * now do the regex wizardry. 00506 */ 00507 00508 if (regcomp(&preg, pattern, REG_EXTENDED | REG_NEWLINE)) { 00509 ast_log(LOG_WARNING, "NAPTR Regex compilation error (regex = \"%s\").\n", regexp); 00510 return -1; 00511 } 00512 00513 if (preg.re_nsub > ARRAY_LEN(pmatch)) { 00514 ast_log(LOG_WARNING, "NAPTR Regex compilation error: too many subs.\n"); 00515 regfree(&preg); 00516 return -1; 00517 } 00518 /* pmatch is an array containing the substring indexes for the regex backreference sub. 00519 * max_bt is the maximum number of backreferences allowed to be stored in pmatch */ 00520 if ((rc = regexec(&preg, (char *) naptrinput, max_bt, pmatch, 0))) { 00521 regerror(rc, &preg, errbuff, sizeof(errbuff)); 00522 ast_log(LOG_WARNING, "NAPTR Regex match failed. Reason: %s\n", errbuff); 00523 regfree(&preg); 00524 return -1; 00525 } 00526 regfree(&preg); 00527 00528 d = tempdst; 00529 d_len--; 00530 00531 /* perform the backreference sub. Search the subst for backreferences, 00532 * when a backreference is found, retrieve the backreferences number. 00533 * use the backreference number as an index for pmatch to retrieve the 00534 * beginning and ending indexes of the substring to insert as the backreference. 00535 * if no backreference is found, continue copying the subst into tempdst */ 00536 while (*subst && (d_len > 0)) { 00537 if ((subst[0] == '\\') && isdigit(subst[1])) { /* is this character the beginning of a backreference */ 00538 matchindex = (int) (subst[1] - '0'); 00539 if (matchindex >= ARRAY_LEN(pmatch)) { 00540 ast_log(LOG_WARNING, "Error during regex substitution. Invalid pmatch index.\n"); 00541 return -1; 00542 } 00543 /* pmatch len is 10. we are garanteed a single char 0-9 is a valid index */ 00544 size = pmatch[matchindex].rm_eo - pmatch[matchindex].rm_so; 00545 if (size > d_len) { 00546 ast_log(LOG_WARNING, "Not enough space during NAPTR regex substitution.\n"); 00547 return -1; 00548 } 00549 /* are the pmatch indexes valid for the input length */ 00550 if ((strlen((char *) naptrinput) >= pmatch[matchindex].rm_eo) && (pmatch[matchindex].rm_so <= pmatch[matchindex].rm_eo)) { 00551 memcpy(d, (naptrinput + (int) pmatch[matchindex].rm_so), size); /* copy input substring into backreference marker */ 00552 d_len -= size; 00553 subst += 2; /* skip over backreference characters to next valid character */ 00554 d += size; 00555 } else { 00556 ast_log(LOG_WARNING, "Error during regex substitution. Invalid backreference index.\n"); 00557 return -1; 00558 } 00559 } else if (isprint(*subst)) { 00560 *d++ = *subst++; 00561 d_len--; 00562 } else { 00563 ast_log(LOG_WARNING, "Error during regex substitution.\n"); 00564 return -1; 00565 } 00566 } 00567 *d = 0; 00568 ast_copy_string((char *) dst, tempdst, dstsize); 00569 dst[dstsize - 1] = '\0'; 00570 00571 if (*tech != '\0'){ /* check if it is requested NAPTR */ 00572 if (!strncasecmp(tech, "ALL", techsize)){ 00573 return 0; /* return or count any RR */ 00574 } 00575 if (!strncasecmp(tech_return, tech, sizeof(tech_return) < techsize ? sizeof(tech_return): techsize)){ 00576 ast_copy_string(tech, tech_return, techsize); 00577 return 0; /* we got our RR */ 00578 } else { /* go to the next RR in the DNS answer */ 00579 return 1; 00580 } 00581 } 00582 00583 /* tech was not specified, return first parsed RR */ 00584 ast_copy_string(tech, tech_return, techsize); 00585 00586 return 0; 00587 }
static int private_enum_init | ( | int | reload | ) | [static] |
Initialize the ENUM support subsystem.
Definition at line 968 of file enum.c.
References ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, ebl_alg, enumlock, ENUMLOOKUP_BLR_CC, ENUMLOOKUP_BLR_EBL, ENUMLOOKUP_BLR_TXT, EVENT_FLAG_SYSTEM, ienum_branchlabel, LOG_WARNING, manager_event, and string.
Referenced by ast_enum_init(), and ast_enum_reload().
00969 { 00970 struct ast_config *cfg; 00971 const char *string; 00972 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00973 00974 if ((cfg = ast_config_load2("enum.conf", "enum", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 00975 return 0; 00976 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) { 00977 return 0; 00978 } 00979 00980 /* Destroy existing list */ 00981 ast_mutex_lock(&enumlock); 00982 if (cfg) { 00983 if ((string = ast_variable_retrieve(cfg, "ienum", "branchlabel"))) { 00984 ast_copy_string(ienum_branchlabel, string, sizeof(ienum_branchlabel)); 00985 } 00986 00987 if ((string = ast_variable_retrieve(cfg, "ienum", "ebl_alg"))) { 00988 ebl_alg = ENUMLOOKUP_BLR_CC; /* default */ 00989 00990 if (!strcasecmp(string, "txt")) 00991 ebl_alg = ENUMLOOKUP_BLR_TXT; 00992 else if (!strcasecmp(string, "ebl")) 00993 ebl_alg = ENUMLOOKUP_BLR_EBL; 00994 else if (!strcasecmp(string, "cc")) 00995 ebl_alg = ENUMLOOKUP_BLR_CC; 00996 else 00997 ast_log(LOG_WARNING, "No valid parameter for ienum/ebl_alg.\n"); 00998 } 00999 ast_config_destroy(cfg); 01000 } 01001 ast_mutex_unlock(&enumlock); 01002 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Enum\r\nStatus: Enabled\r\nMessage: ENUM reload Requested\r\n"); 01003 return 0; 01004 }
static int txt_callback | ( | void * | context, | |
unsigned char * | answer, | |||
int | len, | |||
unsigned char * | fullanswer | |||
) | [static] |
Callback for TXT record lookup, /ol version.
Definition at line 145 of file enum.c.
References ast_copy_string(), ast_log(), LOG_WARNING, txt_context::txt, and txt_context::txtlen.
Referenced by blr_txt().
00146 { 00147 struct txt_context *c = context; 00148 unsigned int i; 00149 00150 c->txt[0] = 0; /* default to empty */ 00151 c->txtlen = 0; 00152 00153 if (answer == NULL) { 00154 return 0; 00155 } 00156 00157 /* RFC1035: 00158 * 00159 * <character-string> is a single length octet followed by that number of characters. 00160 * TXT-DATA One or more <character-string>s. 00161 * 00162 * We only take the first string here. 00163 */ 00164 00165 i = *answer++; 00166 len -= 1; 00167 00168 if (i > len) { /* illegal packet */ 00169 ast_log(LOG_WARNING, "txt_callback: malformed TXT record.\n"); 00170 return 0; 00171 } 00172 00173 if (i >= sizeof(c->txt)) { /* too long? */ 00174 ast_log(LOG_WARNING, "txt_callback: TXT record too long.\n"); 00175 i = sizeof(c->txt) - 1; 00176 } 00177 00178 ast_copy_string(c->txt, (char *)answer, i + 1); /* this handles the \0 termination */ 00179 c->txtlen = i; 00180 00181 return 1; 00182 }
int ebl_alg = ENUMLOOKUP_BLR_CC [static] |
ast_mutex_t enumlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 95 of file enum.c.
Referenced by ast_get_enum(), blr_ebl(), blr_txt(), and private_enum_init().
char ienum_branchlabel[32] = "i" [static] |