#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). |
Definition in file enum.h.
int ast_enum_init | ( | void | ) |
Definition at line 994 of file enum.c.
References private_enum_init().
Referenced by main().
00995 { 00996 return private_enum_init(0); 00997 }
int ast_enum_reload | ( | void | ) |
Definition at line 999 of file enum.c.
References private_enum_init().
01000 { 01001 return private_enum_init(1); 01002 }
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 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(), ast_verb, blr_ebl(), blr_txt(), cclen(), chan, 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_verb(2, "ast_get_enum(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 if((p3 = strchr(naptrinput, '*'))) { 00675 *p3='\0'; 00676 } 00677 00678 context->naptrinput = naptrinput; /* The number */ 00679 context->dst = dst; /* Return string */ 00680 context->dstlen = dstlen; 00681 context->tech = tech; 00682 context->techlen = techlen; 00683 context->options = 0; 00684 context->position = record > 0 ? record : 1; 00685 context->count = 0; 00686 context->naptr_rrs = NULL; 00687 context->naptr_rrs_count = 0; 00688 00689 /* 00690 * Process options: 00691 * 00692 * c Return count, not URI 00693 * i Use infrastructure ENUM 00694 * s Do ISN transformation 00695 * d Direct DNS query: no reversing. 00696 * 00697 */ 00698 if (options != NULL) { 00699 if (strchr(options,'s')) { 00700 context->options |= ENUMLOOKUP_OPTIONS_ISN; 00701 } else if (strchr(options,'i')) { 00702 context->options |= ENUMLOOKUP_OPTIONS_IENUM; 00703 } else if (strchr(options,'d')) { 00704 context->options |= ENUMLOOKUP_OPTIONS_DIRECT; 00705 } 00706 if (strchr(options,'c')) { 00707 context->options |= ENUMLOOKUP_OPTIONS_COUNT; 00708 } 00709 if (strchr(number,'*')) { 00710 context->options |= ENUMLOOKUP_OPTIONS_ISN; 00711 } 00712 } 00713 ast_verb(2, "ENUM options(%s): pos=%d, options='%d'\n", options, context->position, context->options); 00714 ast_debug(1, "ast_get_enum(): n='%s', tech='%s', suffix='%s', options='%d', record='%d'\n", 00715 number, tech, suffix, context->options, context->position); 00716 00717 /* 00718 * This code does more than simple RFC3261 ENUM. All these rewriting 00719 * schemes have in common that they build the FQDN for the NAPTR lookup 00720 * by concatenating 00721 * - a number which needs be flipped and "."-seperated (left) 00722 * - some fixed string (middle) 00723 * - an Apex. (apex) 00724 * 00725 * The RFC3261 ENUM is: left=full number, middle="", apex=from args. 00726 * ISN: number = "middle*left", apex=from args 00727 * I-ENUM: EBL parameters build the split, can change apex 00728 * Direct: left="", middle=argument, apex=from args 00729 * 00730 */ 00731 00732 /* default: the whole number will be flipped, no middle domain component */ 00733 ast_copy_string(left, number, sizeof(left)); 00734 middle[0] = '\0'; 00735 /* 00736 * I-ENUM can change the apex, thus we copy it 00737 */ 00738 ast_copy_string(apex, suffix, sizeof(apex)); 00739 /* ISN rewrite */ 00740 if ((context->options & ENUMLOOKUP_OPTIONS_ISN) && (p1 = strchr(number, '*'))) { 00741 *p1++ = '\0'; 00742 ast_copy_string(left, number, sizeof(left)); 00743 ast_copy_string(middle, p1, sizeof(middle) - 1); 00744 strcat(middle, "."); 00745 00746 ast_verb(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 00753 ast_verb(2, "DIRECT ENUM: middle='%s'\n", middle); 00754 /* Infrastructure ENUM rewrite */ 00755 } else if (context->options & ENUMLOOKUP_OPTIONS_IENUM) { 00756 int sdl = 0; 00757 char cc[8]; 00758 char sep[256], n_apex[256]; 00759 int cc_len = cclen(number); 00760 sdl = cc_len; 00761 ast_mutex_lock(&enumlock); 00762 ast_copy_string(sep, ienum_branchlabel, sizeof(sep)); /* default */ 00763 ast_mutex_unlock(&enumlock); 00764 00765 switch (ebl_alg) { 00766 case ENUMLOOKUP_BLR_EBL: 00767 ast_copy_string(cc, number, cc_len); /* cclen() never returns more than 3 */ 00768 sdl = blr_ebl(cc, suffix, sep, sizeof(sep) - 1, n_apex, sizeof(n_apex) - 1); 00769 00770 if (sdl >= 0) { 00771 ast_copy_string(apex, n_apex, sizeof(apex)); 00772 ast_verb(2, "EBL ENUM: sep=%s, apex='%s'\n", sep, n_apex); 00773 } else { 00774 sdl = cc_len; 00775 } 00776 break; 00777 case ENUMLOOKUP_BLR_TXT: 00778 ast_copy_string(cc, number, cc_len); /* cclen() never returns more than 3 */ 00779 sdl = blr_txt(cc, suffix); 00780 00781 if (sdl < 0) 00782 sdl = cc_len; 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_verb(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_verb(2, "ast_get_enum() profiling: %s, %s, %d 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 if (!argcontext) { 00906 for (k = 0; k < context->naptr_rrs_count; k++) { 00907 ast_free(context->naptr_rrs[k].result); 00908 ast_free(context->naptr_rrs[k].tech); 00909 } 00910 ast_free(context->naptr_rrs); 00911 ast_free(context); 00912 } else 00913 *argcontext = context; 00914 00915 return ret; 00916 }
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 918 of file enum.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_debug, chan, context, and errno.
Referenced by function_txtcidname().
00919 { 00920 struct txt_context context; 00921 char tmp[259 + 512]; 00922 int pos = strlen(number) - 1; 00923 int newpos = 0; 00924 int ret = -1; 00925 00926 ast_debug(4, "ast_get_txt: Number = '%s', suffix = '%s'\n", number, suffix); 00927 00928 if (chan && ast_autoservice_start(chan) < 0) { 00929 return -1; 00930 } 00931 00932 if (pos > 128) { 00933 pos = 128; 00934 } 00935 00936 while (pos >= 0) { 00937 if (isdigit(number[pos])) { 00938 tmp[newpos++] = number[pos]; 00939 tmp[newpos++] = '.'; 00940 } 00941 pos--; 00942 } 00943 00944 ast_copy_string(&tmp[newpos], suffix, sizeof(tmp) - newpos); 00945 00946 if (ret < 0) { 00947 ast_debug(2, "No such number found in ENUM: %s (%s)\n", tmp, strerror(errno)); 00948 ret = 0; 00949 } else { 00950 ast_copy_string(txt, context.txt, txtlen); 00951 } 00952 if (chan) { 00953 ret |= ast_autoservice_stop(chan); 00954 } 00955 return ret; 00956 }