dns_naptr.c File Reference

DNS NAPTR Record Support. More...

#include "asterisk.h"
#include <arpa/nameser.h>
#include <resolv.h>
#include <regex.h>
#include "asterisk/dns_core.h"
#include "asterisk/dns_naptr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/dns_internal.h"
#include "asterisk/utils.h"

Include dependency graph for dns_naptr.c:

Go to the source code of this file.

Defines

#define PAST_END_OF_RECORD   ptr >= end_of_record

Enumerations

enum  flags_result { FLAGS_TERMINAL, FLAGS_EMPTY, FLAGS_UNKNOWN, FLAGS_INVALID }
 Result of analyzing NAPTR flags on a record. More...

Functions

const char * ast_dns_naptr_get_flags (const struct ast_dns_record *record)
 Get the flags from a NAPTR record.
unsigned short ast_dns_naptr_get_order (const struct ast_dns_record *record)
 Get the order from a NAPTR record.
unsigned short ast_dns_naptr_get_preference (const struct ast_dns_record *record)
 Get the preference from a NAPTR record.
const char * ast_dns_naptr_get_regexp (const struct ast_dns_record *record)
 Get the regular expression from a NAPTR record.
const char * ast_dns_naptr_get_replacement (const struct ast_dns_record *record)
 Get the replacement value from a NAPTR record.
const char * ast_dns_naptr_get_service (const struct ast_dns_record *record)
 Get the service from a NAPTR record.
static int compare_order (const void *record1, const void *record2)
static int compare_preference (const void *record1, const void *record2)
struct ast_dns_recorddns_naptr_alloc (struct ast_dns_query *query, const char *data, const size_t size)
 Allocate and parse a DNS NAPTR record.
void dns_naptr_sort (struct ast_dns_result *result)
 Sort the NAPTR records on a result.
static enum flags_result interpret_flags (const char *flags, uint8_t flags_size)
 Analyze and interpret NAPTR flags as per RFC 3404.
static int regexp_flags_invalid (const char *flags, const char *end)
 Determine if flags in the regexp are invalid.
static int regexp_invalid (const char *regexp, uint8_t regexp_size)
 Determine if the regexp in a NAPTR record is invalid.
static int regexp_pattern_invalid (const char *pattern, const char *end)
 Determine if the pattern in a regexp is invalid.
static int regexp_repl_invalid (const char *repl, const char *end, char delim)
 Determine if the replacement in the regexp is invalid.
static int services_invalid (const char *services, uint8_t services_size)
 Analyze NAPTR services for validity as defined by RFC 3404.


Detailed Description

DNS NAPTR Record Support.

Author:
Joshua Colp <jcolp@digium.com>

Definition in file dns_naptr.c.


Define Documentation

#define PAST_END_OF_RECORD   ptr >= end_of_record

Definition at line 379 of file dns_naptr.c.

Referenced by dns_naptr_alloc().


Enumeration Type Documentation

Result of analyzing NAPTR flags on a record.

Enumerator:
FLAGS_TERMINAL  Terminal record, meaning the DDDS algorithm can be stopped
FLAGS_EMPTY  No flags provided, likely meaning another NAPTR lookup
FLAGS_UNKNOWN  Unrecognized but valid flags. We cannot conclude what they mean
FLAGS_INVALID  Non-alphanumeric or invalid combination of flags

Definition at line 47 of file dns_naptr.c.

00047                   {
00048    /*! Terminal record, meaning the DDDS algorithm can be stopped */
00049    FLAGS_TERMINAL,
00050    /*! No flags provided, likely meaning another NAPTR lookup */
00051    FLAGS_EMPTY,
00052    /*! Unrecognized but valid flags. We cannot conclude what they mean */
00053    FLAGS_UNKNOWN,
00054    /*! Non-alphanumeric or invalid combination of flags */
00055    FLAGS_INVALID,
00056 };


Function Documentation

const char* ast_dns_naptr_get_flags ( const struct ast_dns_record record  ) 

Get the flags from a NAPTR record.

Parameters:
record The DNS record
Returns:
the flags

Definition at line 591 of file dns_naptr.c.

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_naptr_record::flags.

Referenced by AST_TEST_DEFINE().

00592 {
00593    struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
00594 
00595    ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
00596    return naptr->flags;
00597 }

unsigned short ast_dns_naptr_get_order ( const struct ast_dns_record record  ) 

Get the order from a NAPTR record.

Parameters:
record The DNS record
Returns:
the order

Definition at line 623 of file dns_naptr.c.

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_naptr_record::order.

Referenced by AST_TEST_DEFINE().

00624 {
00625    struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
00626 
00627    ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
00628    return naptr->order;
00629 }

unsigned short ast_dns_naptr_get_preference ( const struct ast_dns_record record  ) 

Get the preference from a NAPTR record.

Parameters:
record The DNS record
Returns:
the preference

Definition at line 631 of file dns_naptr.c.

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_naptr_record::preference.

Referenced by AST_TEST_DEFINE().

00632 {
00633    struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
00634 
00635    ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
00636    return naptr->preference;
00637 }

const char* ast_dns_naptr_get_regexp ( const struct ast_dns_record record  ) 

Get the regular expression from a NAPTR record.

Parameters:
record The DNS record
Returns:
the regular expression

Definition at line 607 of file dns_naptr.c.

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_naptr_record::regexp.

Referenced by AST_TEST_DEFINE().

00608 {
00609    struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
00610 
00611    ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
00612    return naptr->regexp;
00613 }

const char* ast_dns_naptr_get_replacement ( const struct ast_dns_record record  ) 

Get the replacement value from a NAPTR record.

Parameters:
record The DNS record
Returns:
the replacement value

Definition at line 615 of file dns_naptr.c.

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_naptr_record::replacement.

Referenced by AST_TEST_DEFINE().

00616 {
00617    struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
00618 
00619    ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
00620    return naptr->replacement;
00621 }

const char* ast_dns_naptr_get_service ( const struct ast_dns_record record  ) 

Get the service from a NAPTR record.

Parameters:
record The DNS record
Returns:
the service

Definition at line 599 of file dns_naptr.c.

References ast_assert, ast_dns_record_get_rr_type(), and ast_dns_naptr_record::service.

Referenced by AST_TEST_DEFINE().

00600 {
00601    struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
00602 
00603    ast_assert(ast_dns_record_get_rr_type(record) == ns_t_naptr);
00604    return naptr->service;
00605 }

static int compare_order ( const void *  record1,
const void *  record2 
) [static]

Definition at line 514 of file dns_naptr.c.

Referenced by dns_naptr_sort().

00515 {
00516    const struct ast_dns_naptr_record **left = (const struct ast_dns_naptr_record **)record1;
00517    const struct ast_dns_naptr_record **right = (const struct ast_dns_naptr_record **)record2;
00518 
00519    if ((*left)->order < (*right)->order) {
00520       return -1;
00521    } else if ((*left)->order > (*right)->order) {
00522       return 1;
00523    } else {
00524       return 0;
00525    }
00526 }

static int compare_preference ( const void *  record1,
const void *  record2 
) [static]

Definition at line 528 of file dns_naptr.c.

Referenced by dns_naptr_sort().

00529 {
00530    const struct ast_dns_naptr_record **left = (const struct ast_dns_naptr_record **)record1;
00531    const struct ast_dns_naptr_record **right = (const struct ast_dns_naptr_record **)record2;
00532 
00533    if ((*left)->preference < (*right)->preference) {
00534       return -1;
00535    } else if ((*left)->preference > (*right)->preference) {
00536       return 1;
00537    } else {
00538       return 0;
00539    }
00540 }

struct ast_dns_record* dns_naptr_alloc ( struct ast_dns_query query,
const char *  data,
const size_t  size 
) [read]

Allocate and parse a DNS NAPTR record.

Parameters:
query The DNS query
data This specific NAPTR record
size The size of the NAPTR record
Return values:
non-NULL success
NULL failure

Definition at line 381 of file dns_naptr.c.

References ast_dns_result::answer, ast_dns_result::answer_size, ast_assert, ast_calloc, ast_log, ast_dns_naptr_record::data, ast_dns_record::data_ptr, dns_find_record(), dns_parse_short(), dns_parse_string(), errno, ast_dns_naptr_record::flags, FLAGS_INVALID, ast_dns_naptr_record::generic, interpret_flags(), LOG_ERROR, NULL, ast_dns_naptr_record::order, order, PAST_END_OF_RECORD, ast_dns_naptr_record::preference, ast_dns_naptr_record::regexp, regexp_invalid(), ast_dns_naptr_record::replacement, ast_dns_query::result, ast_dns_naptr_record::service, and services_invalid().

00382 {
00383    struct ast_dns_naptr_record *naptr;
00384    char *ptr = NULL;
00385    uint16_t order;
00386    uint16_t preference;
00387    uint8_t flags_size;
00388    char *flags;
00389    uint8_t services_size;
00390    char *services;
00391    uint8_t regexp_size;
00392    char *regexp;
00393    char replacement[256] = "";
00394    int replacement_size;
00395    const char *end_of_record;
00396    enum flags_result flags_res;
00397 
00398    ptr = dns_find_record(data, size, query->result->answer, query->result->answer_size);
00399    ast_assert(ptr != NULL);
00400 
00401    end_of_record = ptr + size;
00402 
00403    /* ORDER */
00404    /* This assignment takes a big-endian 16-bit value and stores it in the
00405     * machine's native byte order. Using this method allows us to avoid potential
00406     * alignment issues in case the order is not on a short-addressable boundary.
00407     * See http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html for
00408     * more information
00409     */
00410    ptr += dns_parse_short((unsigned char *) ptr, &order);
00411    if (PAST_END_OF_RECORD) {
00412       return NULL;
00413    }
00414 
00415    /* PREFERENCE */
00416    ptr += dns_parse_short((unsigned char *) ptr, &preference);
00417    if (PAST_END_OF_RECORD) {
00418       return NULL;
00419    }
00420 
00421    /* FLAGS */
00422    ptr += dns_parse_string(ptr, &flags_size, &flags);
00423    if (PAST_END_OF_RECORD) {
00424       return NULL;
00425    }
00426 
00427    /* SERVICES */
00428    ptr += dns_parse_string(ptr, &services_size, &services);
00429    if (PAST_END_OF_RECORD) {
00430       return NULL;
00431    }
00432 
00433    /* REGEXP */
00434    ptr += dns_parse_string(ptr, &regexp_size, &regexp);
00435    if (PAST_END_OF_RECORD) {
00436       return NULL;
00437    }
00438 
00439    replacement_size = dn_expand((unsigned char *)query->result->answer, (unsigned char *) end_of_record, (unsigned char *) ptr, replacement, sizeof(replacement) - 1);
00440    if (replacement_size < 0) {
00441       ast_log(LOG_ERROR, "Failed to expand domain name: %s\n", strerror(errno));
00442       return NULL;
00443    }
00444 
00445    ptr += replacement_size;
00446 
00447    if (ptr != end_of_record) {
00448       ast_log(LOG_ERROR, "NAPTR record gave undersized string indications.\n");
00449       return NULL;
00450    }
00451 
00452    /* We've validated the size of the NAPTR record. Now we can validate
00453     * the individual parts
00454     */
00455    flags_res = interpret_flags(flags, flags_size);
00456    if (flags_res == FLAGS_INVALID) {
00457       ast_log(LOG_ERROR, "NAPTR Record contained invalid flags %.*s\n", flags_size, flags);
00458       return NULL;
00459    }
00460 
00461    if (services_invalid(services, services_size)) {
00462       ast_log(LOG_ERROR, "NAPTR record contained invalid services %.*s\n", services_size, services);
00463       return NULL;
00464    }
00465 
00466    if (regexp_invalid(regexp, regexp_size)) {
00467       ast_log(LOG_ERROR, "NAPTR record contained invalid regexp %.*s\n", regexp_size, regexp);
00468       return NULL;
00469    }
00470 
00471    /* replacement_size takes into account the NULL label, so a NAPTR record with no replacement
00472     * will have a replacement_size of 1.
00473     */
00474    if (regexp_size && replacement_size > 1) {
00475       ast_log(LOG_ERROR, "NAPTR record contained both a regexp and replacement\n");
00476       return NULL;
00477    }
00478 
00479    naptr = ast_calloc(1, sizeof(*naptr) + size + flags_size + 1 + services_size + 1 + regexp_size + 1 + replacement_size + 1);
00480    if (!naptr) {
00481       return NULL;
00482    }
00483 
00484    naptr->order = order;
00485    naptr->preference = preference;
00486 
00487    ptr = naptr->data;
00488    ptr += size;
00489 
00490    strncpy(ptr, flags, flags_size);
00491    ptr[flags_size] = '\0';
00492    naptr->flags = ptr;
00493    ptr += flags_size + 1;
00494 
00495    strncpy(ptr, services, services_size);
00496    ptr[services_size] = '\0';
00497    naptr->service = ptr;
00498    ptr += services_size + 1;
00499 
00500    strncpy(ptr, regexp, regexp_size);
00501    ptr[regexp_size] = '\0';
00502    naptr->regexp = ptr;
00503    ptr += regexp_size + 1;
00504 
00505    strcpy(ptr, replacement);
00506    naptr->replacement = ptr;
00507 
00508    naptr->generic.data_ptr = naptr->data;
00509 
00510    return (struct ast_dns_record *)naptr;
00511 }

void dns_naptr_sort ( struct ast_dns_result result  ) 

Sort the NAPTR records on a result.

Parameters:
result The DNS result

Definition at line 542 of file dns_naptr.c.

References ast_alloca, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, compare_order(), compare_preference(), order, ast_dns_naptr_record::order, and records.

00543 {
00544    struct ast_dns_record *current;
00545    size_t num_records = 0;
00546    struct ast_dns_naptr_record **records;
00547    int i = 0;
00548    int j = 0;
00549    int cur_order;
00550 
00551    /* Determine the number of records */
00552    AST_LIST_TRAVERSE(&result->records, current, list) {
00553       ++num_records;
00554    }
00555 
00556    /* No point in continuing if there are no records */
00557    if (num_records == 0) {
00558       return;
00559    }
00560 
00561    /* Allocate an array with that number of records */
00562    records = ast_alloca(num_records * sizeof(*records));
00563 
00564    /* Move records from the list to the array */
00565    AST_LIST_TRAVERSE_SAFE_BEGIN(&result->records, current, list) {
00566       records[i++] = (struct ast_dns_naptr_record *) current;
00567       AST_LIST_REMOVE_CURRENT(list);
00568    }
00569    AST_LIST_TRAVERSE_SAFE_END;
00570 
00571    /* Sort the array by order */
00572    qsort(records, num_records, sizeof(*records), compare_order);
00573 
00574    /* Sort subarrays by preference */
00575    for (i = 0; i < num_records; i = j) {
00576       cur_order = records[i]->order;
00577       for (j = i + 1; j < num_records; ++j) {
00578          if (records[j]->order != cur_order) {
00579             break;
00580          }
00581       }
00582       qsort(&records[i], j - i, sizeof(*records), compare_preference);
00583    }
00584 
00585    /* Place sorted records back into the original list */
00586    for (i = 0; i < num_records; ++i) {
00587       AST_LIST_INSERT_TAIL(&result->records, (struct ast_dns_record *)(records[i]), list);
00588    }
00589 }

static enum flags_result interpret_flags ( const char *  flags,
uint8_t  flags_size 
) [static]

Analyze and interpret NAPTR flags as per RFC 3404.

Note:
The flags string passed into this function is NOT NULL-terminated
Parameters:
flags The flags string from a NAPTR record The size of the flags string in bytes
Returns:
flag result

Definition at line 67 of file dns_naptr.c.

References FLAGS_EMPTY, FLAGS_INVALID, FLAGS_TERMINAL, and FLAGS_UNKNOWN.

Referenced by dns_naptr_alloc().

00068 {
00069    int i;
00070    char known_flag_found = 0;
00071 
00072    if (flags_size == 0) {
00073       return FLAGS_EMPTY;
00074    }
00075 
00076    /* Take care of the most common (and easy) case, one character */
00077    if (flags_size == 1) {
00078       if (*flags == 's' || *flags == 'S' ||
00079             *flags == 'a' || *flags == 'A' ||
00080             *flags == 'u' || *flags == 'U') {
00081          return FLAGS_TERMINAL;
00082       } else if (!isalnum(*flags)) {
00083          return FLAGS_INVALID;
00084       } else {
00085          return FLAGS_UNKNOWN;
00086       }
00087    }
00088 
00089    /*
00090     * Multiple flags are allowed, but you cannot mix the
00091     * S, A, U, and P flags together.
00092     */
00093    for (i = 0; i < flags_size; ++i) {
00094       if (!isalnum(flags[i])) {
00095          return FLAGS_INVALID;
00096       } else if (flags[i] == 's' || flags[i] == 'S') {
00097          if (known_flag_found && known_flag_found != 's') {
00098             return FLAGS_INVALID;
00099          }
00100          known_flag_found = 's';
00101       } else if (flags[i] == 'u' || flags[i] == 'U') {
00102          if (known_flag_found && known_flag_found != 'u') {
00103             return FLAGS_INVALID;
00104          }
00105          known_flag_found = 'u';
00106       } else if (flags[i] == 'a' || flags[i] == 'A') {
00107          if (known_flag_found && known_flag_found != 'a') {
00108             return FLAGS_INVALID;
00109          }
00110          known_flag_found = 'a';
00111       } else if (flags[i] == 'p' || flags[i] == 'P') {
00112          if (known_flag_found && known_flag_found != 'p') {
00113             return FLAGS_INVALID;
00114          }
00115          known_flag_found = 'p';
00116       }
00117    }
00118 
00119    return (!known_flag_found || known_flag_found == 'p') ? FLAGS_UNKNOWN : FLAGS_TERMINAL;
00120 }

static int regexp_flags_invalid ( const char *  flags,
const char *  end 
) [static]

Determine if flags in the regexp are invalid.

A NAPTR regexp is structured like so /pattern/repl/FLAGS

This ensures that the flags on the regexp are valid. Regexp flags can either be zero or one character long. If the flags are one character long, that character must be "i" to indicate the regex evaluation is case-insensitive.

Note:
The flags string passed to this function is not NULL-terminated
Parameters:
flags The regexp flags from the NAPTR record
end A pointer to the end of the flags string
Return values:
0 Flags are valid
-1 Flags are invalid

Definition at line 190 of file dns_naptr.c.

Referenced by regexp_invalid().

00191 {
00192    if (flags >= end) {
00193       return 0;
00194    }
00195 
00196    if (end - flags > 1) {
00197       return -1;
00198    }
00199 
00200    if (*flags != 'i') {
00201       return -1;
00202    }
00203 
00204    return 0;
00205 }

static int regexp_invalid ( const char *  regexp,
uint8_t  regexp_size 
) [static]

Determine if the regexp in a NAPTR record is invalid.

The goal of this function is to divide the regexp into its constituent parts and then let validation subroutines determine if each part is valid. If all parts are valid, then the entire regexp is valid.

Note:
The regexp string passed to this function is NOT NULL-terminated
Parameters:
regexp The regexp from the NAPTR record
regexp_size The size of the regexp string
Return values:
0 regexp is valid
non-zero regexp is invalid

Definition at line 310 of file dns_naptr.c.

References regexp_flags_invalid(), regexp_pattern_invalid(), and regexp_repl_invalid().

Referenced by dns_naptr_alloc().

00311 {
00312    char delim;
00313    const char *delim2_pos;
00314    const char *delim3_pos;
00315    const char *ptr = regexp;
00316    const char *end_of_regexp = regexp + regexp_size;
00317    const char *regex_pos;
00318    const char *repl_pos;
00319    const char *flags_pos;
00320 
00321    if (regexp_size == 0) {
00322       return 0;
00323    }
00324 
00325    /* The delimiter will be a ! or / in most cases, but the rules allow
00326     * for the delimiter to be nearly any character. It cannot be 'i' because
00327     * the delimiter cannot be the same as regexp flags. The delimiter cannot
00328     * be 1-9 because the delimiter cannot be a backreference number. RFC
00329     * 2915 specified that backslash was also not allowed as a delimiter, but
00330     * RFC 3402 does not say this. We've gone ahead and made the character
00331     * illegal for our purposes.
00332     */
00333    delim = *ptr;
00334    if (strchr("123456789\\i", delim)) {
00335       return -1;
00336    }
00337    ++ptr;
00338    regex_pos = ptr;
00339 
00340    /* Find the other two delimiters. If the delim is escaped with a backslash, it doesn't count */
00341    while (1) {
00342       delim2_pos = memchr(ptr, delim, end_of_regexp - ptr);
00343       if (!delim2_pos) {
00344          return -1;
00345       }
00346       ptr = delim2_pos + 1;
00347       if (delim2_pos[-1] != '\\') {
00348          break;
00349       }
00350    }
00351 
00352    if (ptr >= end_of_regexp) {
00353       return -1;
00354    }
00355 
00356    repl_pos = ptr;
00357 
00358    while (1) {
00359       delim3_pos = memchr(ptr, delim, end_of_regexp - ptr);
00360       if (!delim3_pos) {
00361          return -1;
00362       }
00363       ptr = delim3_pos + 1;
00364       if (delim3_pos[-1] != '\\') {
00365          break;
00366       }
00367    }
00368    flags_pos = ptr;
00369 
00370    if (regexp_flags_invalid(flags_pos, end_of_regexp) ||
00371          regexp_repl_invalid(repl_pos, delim3_pos, delim) ||
00372          regexp_pattern_invalid(regex_pos, delim2_pos)) {
00373       return -1;
00374    }
00375 
00376    return 0;
00377 }

static int regexp_pattern_invalid ( const char *  pattern,
const char *  end 
) [static]

Determine if the pattern in a regexp is invalid.

A NAPTR regexp is structured like so /PATTERN/repl/flags

This ensures that the pattern on the regexp is valid. The pattern is passed to a regex compiler to determine its validity.

Note:
The pattern string passed to this function is NOT NULL-terminated
Parameters:
pattern The pattern from the NAPTR record
end A pointer to the end of the pattern
Return values:
0 Pattern is valid
non-zero Pattern is invalid

Definition at line 276 of file dns_naptr.c.

Referenced by regexp_invalid().

00277 {
00278    int pattern_size = end - pattern;
00279    char pattern_str[pattern_size + 1];
00280    regex_t reg;
00281    int res;
00282 
00283    /* regcomp requires a NULL-terminated string */
00284    memcpy(pattern_str, pattern, pattern_size);
00285    pattern_str[pattern_size] = '\0';
00286 
00287    res = regcomp(&reg, pattern_str, REG_EXTENDED);
00288 
00289    regfree(&reg);
00290 
00291    return res;
00292 }

static int regexp_repl_invalid ( const char *  repl,
const char *  end,
char  delim 
) [static]

Determine if the replacement in the regexp is invalid.

A NAPTR regexp is structured like so /pattern/REPL/flags

This ensures that the replacement on the regexp is valid. The regexp replacement is free to use any character it wants, plus backreferences and an escaped regexp delimiter.

This function does not attempt to ensure that the backreferences refer to valid portions of the regexp's regex pattern.

Note:
The repl string passed to this function is NOT NULL-terminated
Parameters:
repl The regexp replacement string
end Pointer to the end of the replacement string
delim The delimiter character for the regexp
Return values:
0 Replacement is valid
-1 Replacement is invalid

Definition at line 229 of file dns_naptr.c.

References ast_assert.

Referenced by regexp_invalid().

00230 {
00231    const char *ptr = repl;
00232 
00233    if (repl == end) {
00234       /* Kind of weird, but this is fine */
00235       return 0;
00236    }
00237 
00238    while (1) {
00239       char *backslash_pos = memchr(ptr, '\\', end - ptr);
00240       if (!backslash_pos) {
00241          break;
00242       }
00243 
00244       ast_assert(backslash_pos < end - 1);
00245 
00246       /* XXX RFC 3402 is unclear about whether other backslash-escaped characters
00247        * (such as a backslash-escaped backslash) are legal
00248        */
00249       if (!strchr("12345689", backslash_pos[1]) && backslash_pos[1] != delim) {
00250          return -1;
00251       }
00252 
00253       ptr = backslash_pos + 1;
00254    }
00255 
00256    return 0;
00257 }

static int services_invalid ( const char *  services,
uint8_t  services_size 
) [static]

Analyze NAPTR services for validity as defined by RFC 3404.

Note:
The services string passed to this function is NOT NULL-terminated
Parameters:
services The services string parsed from a NAPTR record
services_size The size of the services string
Return values:
0 Services are valid
-1 Services are invalid

Definition at line 131 of file dns_naptr.c.

Referenced by dns_naptr_alloc().

00132 {
00133    const char *current_pos = services;
00134    const char *end_of_services = services + services_size;
00135 
00136    if (services_size == 0) {
00137       return 0;
00138    }
00139 
00140    /* Services are broken into sections divided by a + sign. Each section
00141     * must start with an alphabetic character, and then can only contain
00142     * alphanumeric characters. The size of any section is limited to
00143     * 32 characters
00144     */
00145    while (1) {
00146       char *plus_pos = memchr(current_pos, '+', end_of_services - current_pos);
00147       uint8_t current_size = plus_pos ? plus_pos - current_pos : end_of_services - current_pos;
00148       int i;
00149 
00150       if (!isalpha(current_pos[0])) {
00151          return -1;
00152       }
00153 
00154       if (current_size > 32) {
00155          return -1;
00156       }
00157 
00158       for (i = 1; i < current_size; ++i) {
00159          if (!isalnum(current_pos[i])) {
00160             return -1;
00161          }
00162       }
00163 
00164       if (!plus_pos) {
00165          break;
00166       }
00167       current_pos = plus_pos + 1;
00168    }
00169 
00170    return 0;
00171 }


Generated on Thu Apr 16 06:30:42 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6