ENUM Support for Asterisk. More...
#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) |
ENUM lookup. | |
int | ast_get_txt (struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen, char *txt, int txtlen) |
Get TXT record from DNS. Really has nothing to do with enum, but anyway... | |
AST_MUTEX_DEFINE_STATIC (enumlock) | |
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 int | enumver |
static struct enum_search * | toplevs |
ENUM Support for Asterisk.
Definition in file enum.c.
#define ENUMLOOKUP_OPTIONS_COUNT 1 |
Definition at line 316 of file enum.c.
Referenced by ast_get_enum(), and enum_callback().
#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(), free, ast_variable::name, ast_variable::next, enum_search::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 * | dst, | |||
int | dstlen, | |||
char * | tech, | |||
int | techlen, | |||
char * | suffix, | |||
char * | options, | |||
unsigned int | record | |||
) |
ENUM lookup.
Lookup entry in ENUM Returns 1 if found, 0 if not found, -1 on hangup.
Definition at line 409 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(), enum_context::dst, enum_context::dstlen, enum_callback(), ENUMLOOKUP_OPTIONS_COUNT, errno, free, LOG_DEBUG, enum_naptr_rr::naptr, enum_context::naptr_rrs, enum_context::naptr_rrs_count, enum_context::naptrinput, enum_search::next, enum_context::options, naptr::order, enum_context::position, naptr::pref, enum_naptr_rr::result, s, enum_naptr_rr::sort_pos, enum_naptr_rr::tech, enum_context::tech, enum_context::techlen, enum_search::toplev, 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 * | dst, | |||
int | dstlen, | |||
char * | tech, | |||
int | techlen, | |||
char * | txt, | |||
int | txtlen | |||
) |
Get TXT record from DNS. Really has nothing to do with enum, but anyway...
Lookup DNS TXT record (used by app TXTCIDnum.
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(), enum_context::dst, enum_context::dstlen, errno, LOG_DEBUG, enum_context::naptrinput, enum_search::next, option_debug, s, enum_context::tech, enum_context::techlen, enum_search::toplev, toplevs, enum_context::txt, txt_callback(), and enum_context::txtlen.
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 }
AST_MUTEX_DEFINE_STATIC | ( | enumlock | ) |
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, read] |
Add enum tree to linked list.
Definition at line 635 of file enum.c.
References ast_calloc, ast_copy_string(), and enum_search::toplev.
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 }
struct enum_search * toplevs [static] |
Referenced by ast_enum_init(), ast_get_enum(), and ast_get_txt().