32#include <arpa/nameser.h> 
   33#include <netinet/in.h> 
   69    char known_flag_found = 0;
 
   71    if (flags_size == 0) {
 
   76    if (flags_size == 1) {
 
   77        if (*flags == 
's' || *flags == 
'S' ||
 
   78                *flags == 
'a' || *flags == 
'A' ||
 
   79                *flags == 
'u' || *flags == 
'U') {
 
   81        } 
else if (!isalnum(*flags)) {
 
   92    for (i = 0; i < flags_size; ++i) {
 
   93        if (!isalnum(flags[i])) {
 
   95        } 
else if (flags[i] == 
's' || flags[i] == 
'S') {
 
   96            if (known_flag_found && known_flag_found != 
's') {
 
   99            known_flag_found = 
's';
 
  100        } 
else if (flags[i] == 
'u' || flags[i] == 
'U') {
 
  101            if (known_flag_found && known_flag_found != 
'u') {
 
  104            known_flag_found = 
'u';
 
  105        } 
else if (flags[i] == 
'a' || flags[i] == 
'A') {
 
  106            if (known_flag_found && known_flag_found != 
'a') {
 
  109            known_flag_found = 
'a';
 
  110        } 
else if (flags[i] == 
'p' || flags[i] == 
'P') {
 
  111            if (known_flag_found && known_flag_found != 
'p') {
 
  114            known_flag_found = 
'p';
 
 
  132    const char *current_pos = services;
 
  133    const char *end_of_services = services + services_size;
 
  135    if (services_size == 0) {
 
  145        char *plus_pos = memchr(current_pos, 
'+', end_of_services - current_pos);
 
  146        uint8_t current_size = plus_pos ? plus_pos - current_pos : end_of_services - current_pos;
 
  149        if (!isalpha(current_pos[0])) {
 
  153        if (current_size > 32) {
 
  157        for (i = 1; i < current_size; ++i) {
 
  158            if (!isalnum(current_pos[i])) {
 
  166        current_pos = plus_pos + 1;
 
 
  195    if (
end - flags > 1) {
 
 
  230    const char *ptr = repl;
 
  238        char *backslash_pos = memchr(ptr, 
'\\', 
end - ptr);
 
  239        if (!backslash_pos) {
 
  248        if (!strchr(
"12345689", backslash_pos[1]) && backslash_pos[1] != delim) {
 
  252        ptr = backslash_pos + 1;
 
 
  277    int pattern_size = 
end - pattern;
 
  278    char pattern_str[pattern_size + 1];
 
  283    memcpy(pattern_str, pattern, pattern_size);
 
  284    pattern_str[pattern_size] = 
'\0';
 
  286    res = regcomp(®, pattern_str, REG_EXTENDED);
 
 
  312    const char *delim2_pos;
 
  313    const char *delim3_pos;
 
  314    const char *ptr = regexp;
 
  315    const char *end_of_regexp = regexp + regexp_size;
 
  316    const char *regex_pos;
 
  317    const char *repl_pos;
 
  318    const char *flags_pos;
 
  320    if (regexp_size == 0) {
 
  333    if (strchr(
"123456789\\i", delim)) {
 
  341        delim2_pos = memchr(ptr, delim, end_of_regexp - ptr);
 
  345        ptr = delim2_pos + 1;
 
  346        if (delim2_pos[-1] != 
'\\') {
 
  351    if (ptr >= end_of_regexp) {
 
  358        delim3_pos = memchr(ptr, delim, end_of_regexp - ptr);
 
  362        ptr = delim3_pos + 1;
 
  363        if (delim3_pos[-1] != 
'\\') {
 
 
  378#define PAST_END_OF_RECORD ptr >= end_of_record 
  388    uint8_t services_size;
 
  393    int replacement_size;
 
  394    const char *end_of_record;
 
  401    end_of_record = ptr + size;
 
  444    replacement_size = dn_expand((
unsigned char *)query->
result->
answer,
 
  445        (
unsigned char *) end_of_record, (
unsigned char *) ptr,
 
  447    if (replacement_size < 0) {
 
  452    ptr += replacement_size;
 
  454    if (ptr != end_of_record) {
 
  469        ast_log(
LOG_ERROR, 
"NAPTR record contained invalid services %.*s\n", services_size, services);
 
  481    if (regexp_size && replacement_size > 1) {
 
  482        ast_log(
LOG_ERROR, 
"NAPTR record contained both a regexp and replacement\n");
 
  486    naptr_len = 
sizeof(*naptr) + size + flags_size + 1 + services_size + 1
 
  499    strncpy(ptr, 
flags, flags_size);
 
  500    ptr[flags_size] = 
'\0';
 
  502    ptr += flags_size + 1;
 
  504    strncpy(ptr, services, services_size);
 
  505    ptr[services_size] = 
'\0';
 
  506    naptr->service = ptr;
 
  507    ptr += services_size + 1;
 
  509    strncpy(ptr, 
regexp, regexp_size);
 
  510    ptr[regexp_size] = 
'\0';
 
  512    ptr += regexp_size + 1;
 
  515    naptr->replacement = ptr;
 
 
  528    if ((*left)->order < (*right)->order) {
 
  530    } 
else if ((*left)->order > (*right)->order) {
 
 
  542    if ((*left)->preference < (*right)->preference) {
 
  544    } 
else if ((*left)->preference > (*right)->preference) {
 
 
  554    size_t num_records = 0;
 
  566    if (num_records == 0) {
 
  584    for (i = 0; i < num_records; i = j) {
 
  586        for (j = i + 1; j < num_records; ++j) {
 
  595    for (i = 0; i < num_records; ++i) {
 
 
  613    return naptr->service;
 
 
  621    return naptr->regexp;
 
 
  629    return naptr->replacement;
 
 
  645    return naptr->preference;
 
 
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_calloc(num, len)
A wrapper for calloc()
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
Internal DNS structure definitions.
char * dns_find_record(const char *record, size_t record_size, const char *response, size_t response_size)
Find the location of a DNS record within the entire DNS answer.
int dns_parse_short(unsigned char *cur, uint16_t *val)
Parse a 16-bit unsigned value from a DNS record.
int dns_parse_string(char *cur, uint8_t *size, char **val)
Parse a DNS string from a DNS record.
void dns_naptr_sort(struct ast_dns_result *result)
Sort the NAPTR records on a result.
const char * ast_dns_naptr_get_replacement(const struct ast_dns_record *record)
Get the replacement value from a NAPTR record.
struct ast_dns_record * dns_naptr_alloc(struct ast_dns_query *query, const char *data, const size_t size)
Allocate and parse a DNS NAPTR record.
#define PAST_END_OF_RECORD
static int regexp_flags_invalid(const char *flags, const char *end)
Determine if flags in the regexp are invalid.
unsigned short ast_dns_naptr_get_preference(const struct ast_dns_record *record)
Get the preference from a NAPTR record.
static int regexp_repl_invalid(const char *repl, const char *end, char delim)
Determine if the replacement in the regexp is invalid.
const char * ast_dns_naptr_get_flags(const struct ast_dns_record *record)
Get the flags from a NAPTR record.
static int regexp_pattern_invalid(const char *pattern, const char *end)
Determine if the pattern in a regexp is invalid.
const char * ast_dns_naptr_get_service(const struct ast_dns_record *record)
Get the service from a NAPTR record.
static int services_invalid(const char *services, uint8_t services_size)
Analyze NAPTR services for validity as defined by RFC 3404.
static int regexp_invalid(const char *regexp, uint8_t regexp_size)
Determine if the regexp in a NAPTR record is invalid.
const char * ast_dns_naptr_get_regexp(const struct ast_dns_record *record)
Get the regular expression from a NAPTR record.
unsigned short ast_dns_naptr_get_order(const struct ast_dns_record *record)
Get the order from a NAPTR record.
static enum flags_result interpret_flags(const char *flags, uint8_t flags_size)
Analyze and interpret NAPTR flags as per RFC 3404.
static int compare_order(const void *record1, const void *record2)
flags_result
Result of analyzing NAPTR flags on a record.
static int compare_preference(const void *record1, const void *record2)
DNS NAPTR Record Parsing API.
A set of macros to manage forward-linked lists.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
unsigned short preference
The preference of the NAPTR record.
const char * regexp
The regular expression from the NAPTR record.
char data[0]
Buffer for NAPTR-specific data.
const char * flags
The flags from the NAPTR record.
const char * replacement
The replacement from the NAPTR record.
struct ast_dns_result * result
Result of the DNS query.
char data[0]
The raw DNS record.
The result of a DNS query.
size_t answer_size
The size of the raw DNS answer.
const char * answer
The raw DNS answer.