#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"
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) |
Lookup entry in ENUM Returns 1 if found, 0 if not found, -1 on hangup. | |
int | ast_get_txt (struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen, char *txt, int txtlen) |
Lookup DNS TXT record (used by app TXTCIDnum. | |
static int | enum_callback (void *context, unsigned char *answer, int len, unsigned char *fullanswer) |
Callback from ENUM lookup function. | |
static struct enum_search * | enum_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_search * | toplevs |
Definition in file enum.c.
#define ENUMLOOKUP_OPTIONS_COUNT 1 |
#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().
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, 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 * | location, | |||
int | maxloc, | |||
char * | technology, | |||
int | maxtech, | |||
char * | suffix, | |||
char * | options, | |||
unsigned int | record | |||
) |
Lookup entry in ENUM Returns 1 if found, 0 if not found, -1 on hangup.
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 empty string | |
maxtech | Max length | |
suffix | Zone suffix (if is NULL then use enum.conf 'search' variable) | |
options | Options ('c' to count number of NAPTR RR) | |
record | The position of required RR in the answer list |
Definition at line 409 of file enum.c.
References ast_autoservice_start(), ast_copy_string(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_search_dns(), context, enum_callback(), enumlock, ENUMLOOKUP_OPTIONS_COUNT, errno, LOG_DEBUG, enum_context::naptrinput, s, 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 * | location, | |||
int | maxloc, | |||
char * | technology, | |||
int | maxtech, | |||
char * | txt, | |||
int | maxtxt | |||
) |
Lookup DNS TXT record (used by app TXTCIDnum.
chan | Channel | |
number | E164 number with or without the leading + | |
location | Number returned (or SIP uri) | |
maxloc | Max length of number | |
technology | Technology (not used in TXT records) | |
maxtech | Max length | |
txt | Text string (return value) | |
maxtxt | Max length of "txt" |
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(), context, enumlock, errno, LOG_DEBUG, enum_context::naptrinput, option_debug, s, toplevs, and txt_callback().
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] |
Add enum tree to linked list.
Definition at line 635 of file enum.c.
References ast_calloc, and ast_copy_string().
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 }
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().
struct enum_search * toplevs [static] |
Referenced by ast_enum_init(), ast_get_enum(), and ast_get_txt().