Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Macros | Enumerations | Functions
dns_naptr.c File Reference

DNS NAPTR Record Support. More...

#include "asterisk.h"
#include <arpa/nameser.h>
#include <netinet/in.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.

Macros

#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. More...
 
unsigned short ast_dns_naptr_get_order (const struct ast_dns_record *record)
 Get the order from a NAPTR record. More...
 
unsigned short ast_dns_naptr_get_preference (const struct ast_dns_record *record)
 Get the preference from a NAPTR record. More...
 
const char * ast_dns_naptr_get_regexp (const struct ast_dns_record *record)
 Get the regular expression from a NAPTR record. More...
 
const char * ast_dns_naptr_get_replacement (const struct ast_dns_record *record)
 Get the replacement value from a NAPTR record. More...
 
const char * ast_dns_naptr_get_service (const struct ast_dns_record *record)
 Get the service from a NAPTR record. More...
 
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. More...
 
void dns_naptr_sort (struct ast_dns_result *result)
 Sort the NAPTR records on a result. More...
 
static enum flags_result interpret_flags (const char *flags, uint8_t flags_size)
 Analyze and interpret NAPTR flags as per RFC 3404. More...
 
static int regexp_flags_invalid (const char *flags, const char *end)
 Determine if flags in the regexp are invalid. More...
 
static int regexp_invalid (const char *regexp, uint8_t regexp_size)
 Determine if the regexp in a NAPTR record is invalid. More...
 
static int regexp_pattern_invalid (const char *pattern, const char *end)
 Determine if the pattern in a regexp is invalid. More...
 
static int regexp_repl_invalid (const char *repl, const char *end, char delim)
 Determine if the replacement in the regexp is invalid. More...
 
static int services_invalid (const char *services, uint8_t services_size)
 Analyze NAPTR services for validity as defined by RFC 3404. More...
 

Detailed Description

DNS NAPTR Record Support.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file dns_naptr.c.

Macro Definition Documentation

◆ PAST_END_OF_RECORD

#define PAST_END_OF_RECORD   ptr >= end_of_record

Definition at line 378 of file dns_naptr.c.

Enumeration Type Documentation

◆ flags_result

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 46 of file dns_naptr.c.

46 {
47 /*! Terminal record, meaning the DDDS algorithm can be stopped */
49 /*! No flags provided, likely meaning another NAPTR lookup */
51 /*! Unrecognized but valid flags. We cannot conclude what they mean */
53 /*! Non-alphanumeric or invalid combination of flags */
55};
@ FLAGS_INVALID
Definition: dns_naptr.c:54
@ FLAGS_UNKNOWN
Definition: dns_naptr.c:52
@ FLAGS_TERMINAL
Definition: dns_naptr.c:48
@ FLAGS_EMPTY
Definition: dns_naptr.c:50

Function Documentation

◆ ast_dns_naptr_get_flags()

const char * ast_dns_naptr_get_flags ( const struct ast_dns_record record)

Get the flags from a NAPTR record.

Parameters
recordThe DNS record
Returns
the flags

Definition at line 600 of file dns_naptr.c.

601{
602 struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
603
604 ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
605 return naptr->flags;
606}
int ast_dns_record_get_rr_type(const struct ast_dns_record *record)
Get the resource record type of a DNS record.
Definition: dns_core.c:145
A NAPTR record.
Definition: dns_internal.h:92
Definition: enum.h:30
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, and ast_dns_record_get_rr_type().

Referenced by AST_TEST_DEFINE().

◆ ast_dns_naptr_get_order()

unsigned short ast_dns_naptr_get_order ( const struct ast_dns_record record)

Get the order from a NAPTR record.

Parameters
recordThe DNS record
Returns
the order

Definition at line 632 of file dns_naptr.c.

633{
634 struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
635
636 ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
637 return naptr->order;
638}
unsigned short order
Definition: enum.h:31

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

Referenced by AST_TEST_DEFINE().

◆ ast_dns_naptr_get_preference()

unsigned short ast_dns_naptr_get_preference ( const struct ast_dns_record record)

Get the preference from a NAPTR record.

Parameters
recordThe DNS record
Returns
the preference

Definition at line 640 of file dns_naptr.c.

641{
642 struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
643
644 ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
645 return naptr->preference;
646}

References ast_assert, and ast_dns_record_get_rr_type().

Referenced by AST_TEST_DEFINE().

◆ ast_dns_naptr_get_regexp()

const char * ast_dns_naptr_get_regexp ( const struct ast_dns_record record)

Get the regular expression from a NAPTR record.

Parameters
recordThe DNS record
Returns
the regular expression

Definition at line 616 of file dns_naptr.c.

617{
618 struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
619
620 ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
621 return naptr->regexp;
622}

References ast_assert, and ast_dns_record_get_rr_type().

Referenced by AST_TEST_DEFINE().

◆ ast_dns_naptr_get_replacement()

const char * ast_dns_naptr_get_replacement ( const struct ast_dns_record record)

Get the replacement value from a NAPTR record.

Parameters
recordThe DNS record
Returns
the replacement value

Definition at line 624 of file dns_naptr.c.

625{
626 struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
627
628 ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
629 return naptr->replacement;
630}

References ast_assert, and ast_dns_record_get_rr_type().

Referenced by AST_TEST_DEFINE().

◆ ast_dns_naptr_get_service()

const char * ast_dns_naptr_get_service ( const struct ast_dns_record record)

Get the service from a NAPTR record.

Parameters
recordThe DNS record
Returns
the service

Definition at line 608 of file dns_naptr.c.

609{
610 struct ast_dns_naptr_record *naptr = (struct ast_dns_naptr_record *) record;
611
612 ast_assert(ast_dns_record_get_rr_type(record) == T_NAPTR);
613 return naptr->service;
614}

References ast_assert, and ast_dns_record_get_rr_type().

Referenced by AST_TEST_DEFINE().

◆ compare_order()

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

Definition at line 523 of file dns_naptr.c.

524{
525 const struct ast_dns_naptr_record **left = (const struct ast_dns_naptr_record **)record1;
526 const struct ast_dns_naptr_record **right = (const struct ast_dns_naptr_record **)record2;
527
528 if ((*left)->order < (*right)->order) {
529 return -1;
530 } else if ((*left)->order > (*right)->order) {
531 return 1;
532 } else {
533 return 0;
534 }
535}

Referenced by dns_naptr_sort().

◆ compare_preference()

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

Definition at line 537 of file dns_naptr.c.

538{
539 const struct ast_dns_naptr_record **left = (const struct ast_dns_naptr_record **)record1;
540 const struct ast_dns_naptr_record **right = (const struct ast_dns_naptr_record **)record2;
541
542 if ((*left)->preference < (*right)->preference) {
543 return -1;
544 } else if ((*left)->preference > (*right)->preference) {
545 return 1;
546 } else {
547 return 0;
548 }
549}

Referenced by dns_naptr_sort().

◆ dns_naptr_alloc()

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.

Parameters
queryThe DNS query
dataThis specific NAPTR record
sizeThe size of the NAPTR record
Return values
non-NULLsuccess
NULLfailure

Definition at line 380 of file dns_naptr.c.

381{
383 char *ptr = NULL;
384 uint16_t order;
385 uint16_t preference;
386 uint8_t flags_size;
387 char *flags;
388 uint8_t services_size;
389 char *services;
390 uint8_t regexp_size;
391 char *regexp;
392 char replacement[256] = "";
393 int replacement_size;
394 const char *end_of_record;
395 enum flags_result flags_res;
396 size_t naptr_len;
397
398 ptr = dns_find_record(data, size, query->result->answer, query->result->answer_size);
399 ast_assert(ptr != NULL);
400
401 end_of_record = ptr + size;
402
403 /* ORDER */
404 /* This assignment takes a big-endian 16-bit value and stores it in the
405 * machine's native byte order. Using this method allows us to avoid potential
406 * alignment issues in case the order is not on a short-addressable boundary.
407 * See http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html for
408 * more information
409 */
410 ptr += dns_parse_short((unsigned char *) ptr, &order);
411 if (PAST_END_OF_RECORD) {
412 return NULL;
413 }
414
415 /* PREFERENCE */
416 ptr += dns_parse_short((unsigned char *) ptr, &preference);
417 if (PAST_END_OF_RECORD) {
418 return NULL;
419 }
420
421 /* FLAGS */
422 ptr += dns_parse_string(ptr, &flags_size, &flags);
423 if (PAST_END_OF_RECORD) {
424 return NULL;
425 }
426
427 /* SERVICES */
428 ptr += dns_parse_string(ptr, &services_size, &services);
429 if (PAST_END_OF_RECORD) {
430 return NULL;
431 }
432
433 /* REGEXP */
434 ptr += dns_parse_string(ptr, &regexp_size, &regexp);
435 if (PAST_END_OF_RECORD) {
436 return NULL;
437 }
438
439 /*
440 * The return value from dn_expand represents the size of the replacement
441 * in the buffer which MAY be compressed. Since the expanded replacement
442 * is NULL terminated, you can use strlen() to get the expanded size.
443 */
444 replacement_size = dn_expand((unsigned char *)query->result->answer,
445 (unsigned char *) end_of_record, (unsigned char *) ptr,
446 replacement, sizeof(replacement) - 1);
447 if (replacement_size < 0) {
448 ast_log(LOG_ERROR, "Failed to expand domain name: %s\n", strerror(errno));
449 return NULL;
450 }
451
452 ptr += replacement_size;
453
454 if (ptr != end_of_record) {
455 ast_log(LOG_ERROR, "NAPTR record gave undersized string indications.\n");
456 return NULL;
457 }
458
459 /* We've validated the size of the NAPTR record. Now we can validate
460 * the individual parts
461 */
462 flags_res = interpret_flags(flags, flags_size);
463 if (flags_res == FLAGS_INVALID) {
464 ast_log(LOG_ERROR, "NAPTR Record contained invalid flags %.*s\n", flags_size, flags);
465 return NULL;
466 }
467
468 if (services_invalid(services, services_size)) {
469 ast_log(LOG_ERROR, "NAPTR record contained invalid services %.*s\n", services_size, services);
470 return NULL;
471 }
472
473 if (regexp_invalid(regexp, regexp_size)) {
474 ast_log(LOG_ERROR, "NAPTR record contained invalid regexp %.*s\n", regexp_size, regexp);
475 return NULL;
476 }
477
478 /* replacement_size takes into account the NULL label, so a NAPTR record with no replacement
479 * will have a replacement_size of 1.
480 */
481 if (regexp_size && replacement_size > 1) {
482 ast_log(LOG_ERROR, "NAPTR record contained both a regexp and replacement\n");
483 return NULL;
484 }
485
486 naptr_len = sizeof(*naptr) + size + flags_size + 1 + services_size + 1
487 + regexp_size + 1 + strlen(replacement) + 1;
488 naptr = ast_calloc(1, naptr_len);
489 if (!naptr) {
490 return NULL;
491 }
492
493 naptr->order = order;
494 naptr->preference = preference;
495
496 ptr = naptr->data;
497 ptr += size;
498
499 strncpy(ptr, flags, flags_size);
500 ptr[flags_size] = '\0';
501 naptr->flags = ptr;
502 ptr += flags_size + 1;
503
504 strncpy(ptr, services, services_size);
505 ptr[services_size] = '\0';
506 naptr->service = ptr;
507 ptr += services_size + 1;
508
509 strncpy(ptr, regexp, regexp_size);
510 ptr[regexp_size] = '\0';
511 naptr->regexp = ptr;
512 ptr += regexp_size + 1;
513
514 strcpy(ptr, replacement);
515 naptr->replacement = ptr;
516
517 naptr->generic.data_ptr = naptr->data;
518
519 return (struct ast_dns_record *)naptr;
520}
integer order
Definition: analys.c:66
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
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.
Definition: dns_core.c:701
int dns_parse_short(unsigned char *cur, uint16_t *val)
Parse a 16-bit unsigned value from a DNS record.
Definition: dns_core.c:722
int dns_parse_string(char *cur, uint8_t *size, char **val)
Parse a DNS string from a DNS record.
Definition: dns_core.c:734
#define PAST_END_OF_RECORD
Definition: dns_naptr.c:378
static int services_invalid(const char *services, uint8_t services_size)
Analyze NAPTR services for validity as defined by RFC 3404.
Definition: dns_naptr.c:130
static int regexp_invalid(const char *regexp, uint8_t regexp_size)
Determine if the regexp in a NAPTR record is invalid.
Definition: dns_naptr.c:309
static enum flags_result interpret_flags(const char *flags, uint8_t flags_size)
Analyze and interpret NAPTR flags as per RFC 3404.
Definition: dns_naptr.c:66
flags_result
Result of analyzing NAPTR flags on a record.
Definition: dns_naptr.c:46
#define LOG_ERROR
int errno
#define NULL
Definition: resample.c:96
unsigned short preference
The preference of the NAPTR record.
Definition: dns_internal.h:106
const char * regexp
The regular expression from the NAPTR record.
Definition: dns_internal.h:100
char data[0]
Buffer for NAPTR-specific data.
Definition: dns_internal.h:113
const char * flags
The flags from the NAPTR record.
Definition: dns_internal.h:96
const char * replacement
The replacement from the NAPTR record.
Definition: dns_internal.h:102
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
For AST_LIST.
Definition: dns_internal.h:39
size_t answer_size
The size of the raw DNS answer.
Definition: dns_internal.h:131
const char * answer
The raw DNS answer.
Definition: dns_internal.h:129

References ast_dns_result::answer, ast_dns_result::answer_size, ast_assert, ast_calloc, ast_log, ast_dns_naptr_record::data, dns_find_record(), dns_parse_short(), dns_parse_string(), errno, ast_dns_naptr_record::flags, FLAGS_INVALID, interpret_flags(), LOG_ERROR, NULL, order, naptr::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, and services_invalid().

◆ dns_naptr_sort()

void dns_naptr_sort ( struct ast_dns_result result)

Sort the NAPTR records on a result.

Parameters
resultThe DNS result

Definition at line 551 of file dns_naptr.c.

552{
553 struct ast_dns_record *current;
554 size_t num_records = 0;
556 int i = 0;
557 int j = 0;
558 int cur_order;
559
560 /* Determine the number of records */
561 AST_LIST_TRAVERSE(&result->records, current, list) {
562 ++num_records;
563 }
564
565 /* No point in continuing if there are no records */
566 if (num_records == 0) {
567 return;
568 }
569
570 /* Allocate an array with that number of records */
571 records = ast_alloca(num_records * sizeof(*records));
572
573 /* Move records from the list to the array */
575 records[i++] = (struct ast_dns_naptr_record *) current;
577 }
579
580 /* Sort the array by order */
581 qsort(records, num_records, sizeof(*records), compare_order);
582
583 /* Sort subarrays by preference */
584 for (i = 0; i < num_records; i = j) {
585 cur_order = records[i]->order;
586 for (j = i + 1; j < num_records; ++j) {
587 if (records[j]->order != cur_order) {
588 break;
589 }
590 }
591 qsort(&records[i], j - i, sizeof(*records), compare_preference);
592 }
593
594 /* Place sorted records back into the original list */
595 for (i = 0; i < num_records; ++i) {
596 AST_LIST_INSERT_TAIL(&result->records, (struct ast_dns_record *)(records[i]), list);
597 }
598}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
static int records
Definition: cdr_pgsql.c:78
static PGresult * result
Definition: cel_pgsql.c:84
static int compare_order(const void *record1, const void *record2)
Definition: dns_naptr.c:523
static int compare_preference(const void *record1, const void *record2)
Definition: dns_naptr.c:537
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
size_t current
Definition: main/cli.c:113

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(), current, order, records, and result.

◆ interpret_flags()

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
flagsThe flags string from a NAPTR record
flags_sizeThe size of the flags string in bytes
Returns
flag result

Definition at line 66 of file dns_naptr.c.

67{
68 int i;
69 char known_flag_found = 0;
70
71 if (flags_size == 0) {
72 return FLAGS_EMPTY;
73 }
74
75 /* Take care of the most common (and easy) case, one character */
76 if (flags_size == 1) {
77 if (*flags == 's' || *flags == 'S' ||
78 *flags == 'a' || *flags == 'A' ||
79 *flags == 'u' || *flags == 'U') {
80 return FLAGS_TERMINAL;
81 } else if (!isalnum(*flags)) {
82 return FLAGS_INVALID;
83 } else {
84 return FLAGS_UNKNOWN;
85 }
86 }
87
88 /*
89 * Multiple flags are allowed, but you cannot mix the
90 * S, A, U, and P flags together.
91 */
92 for (i = 0; i < flags_size; ++i) {
93 if (!isalnum(flags[i])) {
94 return FLAGS_INVALID;
95 } else if (flags[i] == 's' || flags[i] == 'S') {
96 if (known_flag_found && known_flag_found != 's') {
97 return FLAGS_INVALID;
98 }
99 known_flag_found = 's';
100 } else if (flags[i] == 'u' || flags[i] == 'U') {
101 if (known_flag_found && known_flag_found != 'u') {
102 return FLAGS_INVALID;
103 }
104 known_flag_found = 'u';
105 } else if (flags[i] == 'a' || flags[i] == 'A') {
106 if (known_flag_found && known_flag_found != 'a') {
107 return FLAGS_INVALID;
108 }
109 known_flag_found = 'a';
110 } else if (flags[i] == 'p' || flags[i] == 'P') {
111 if (known_flag_found && known_flag_found != 'p') {
112 return FLAGS_INVALID;
113 }
114 known_flag_found = 'p';
115 }
116 }
117
118 return (!known_flag_found || known_flag_found == 'p') ? FLAGS_UNKNOWN : FLAGS_TERMINAL;
119}

References FLAGS_EMPTY, FLAGS_INVALID, FLAGS_TERMINAL, and FLAGS_UNKNOWN.

Referenced by dns_naptr_alloc().

◆ regexp_flags_invalid()

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
flagsThe regexp flags from the NAPTR record
endA pointer to the end of the flags string
Return values
0Flags are valid
-1Flags are invalid

Definition at line 189 of file dns_naptr.c.

190{
191 if (flags >= end) {
192 return 0;
193 }
194
195 if (end - flags > 1) {
196 return -1;
197 }
198
199 if (*flags != 'i') {
200 return -1;
201 }
202
203 return 0;
204}
char * end
Definition: eagi_proxy.c:73

References end.

Referenced by regexp_invalid().

◆ regexp_invalid()

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
regexpThe regexp from the NAPTR record
regexp_sizeThe size of the regexp string
Return values
0regexp is valid
non-zeroregexp is invalid

Definition at line 309 of file dns_naptr.c.

310{
311 char delim;
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;
319
320 if (regexp_size == 0) {
321 return 0;
322 }
323
324 /* The delimiter will be a ! or / in most cases, but the rules allow
325 * for the delimiter to be nearly any character. It cannot be 'i' because
326 * the delimiter cannot be the same as regexp flags. The delimiter cannot
327 * be 1-9 because the delimiter cannot be a backreference number. RFC
328 * 2915 specified that backslash was also not allowed as a delimiter, but
329 * RFC 3402 does not say this. We've gone ahead and made the character
330 * illegal for our purposes.
331 */
332 delim = *ptr;
333 if (strchr("123456789\\i", delim)) {
334 return -1;
335 }
336 ++ptr;
337 regex_pos = ptr;
338
339 /* Find the other two delimiters. If the delim is escaped with a backslash, it doesn't count */
340 while (1) {
341 delim2_pos = memchr(ptr, delim, end_of_regexp - ptr);
342 if (!delim2_pos) {
343 return -1;
344 }
345 ptr = delim2_pos + 1;
346 if (delim2_pos[-1] != '\\') {
347 break;
348 }
349 }
350
351 if (ptr >= end_of_regexp) {
352 return -1;
353 }
354
355 repl_pos = ptr;
356
357 while (1) {
358 delim3_pos = memchr(ptr, delim, end_of_regexp - ptr);
359 if (!delim3_pos) {
360 return -1;
361 }
362 ptr = delim3_pos + 1;
363 if (delim3_pos[-1] != '\\') {
364 break;
365 }
366 }
367 flags_pos = ptr;
368
369 if (regexp_flags_invalid(flags_pos, end_of_regexp) ||
370 regexp_repl_invalid(repl_pos, delim3_pos, delim) ||
371 regexp_pattern_invalid(regex_pos, delim2_pos)) {
372 return -1;
373 }
374
375 return 0;
376}
static int regexp_flags_invalid(const char *flags, const char *end)
Determine if flags in the regexp are invalid.
Definition: dns_naptr.c:189
static int regexp_repl_invalid(const char *repl, const char *end, char delim)
Determine if the replacement in the regexp is invalid.
Definition: dns_naptr.c:228
static int regexp_pattern_invalid(const char *pattern, const char *end)
Determine if the pattern in a regexp is invalid.
Definition: dns_naptr.c:275

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

Referenced by dns_naptr_alloc().

◆ regexp_pattern_invalid()

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
patternThe pattern from the NAPTR record
endA pointer to the end of the pattern
Return values
0Pattern is valid
non-zeroPattern is invalid

Definition at line 275 of file dns_naptr.c.

276{
277 int pattern_size = end - pattern;
278 char pattern_str[pattern_size + 1];
279 regex_t reg;
280 int res;
281
282 /* regcomp requires a NULL-terminated string */
283 memcpy(pattern_str, pattern, pattern_size);
284 pattern_str[pattern_size] = '\0';
285
286 res = regcomp(&reg, pattern_str, REG_EXTENDED);
287
288 regfree(&reg);
289
290 return res;
291}

References end.

Referenced by regexp_invalid().

◆ regexp_repl_invalid()

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
replThe regexp replacement string
endPointer to the end of the replacement string
delimThe delimiter character for the regexp
Return values
0Replacement is valid
-1Replacement is invalid

Definition at line 228 of file dns_naptr.c.

229{
230 const char *ptr = repl;
231
232 if (repl == end) {
233 /* Kind of weird, but this is fine */
234 return 0;
235 }
236
237 while (1) {
238 char *backslash_pos = memchr(ptr, '\\', end - ptr);
239 if (!backslash_pos) {
240 break;
241 }
242
243 ast_assert(backslash_pos < end - 1);
244
245 /* XXX RFC 3402 is unclear about whether other backslash-escaped characters
246 * (such as a backslash-escaped backslash) are legal
247 */
248 if (!strchr("12345689", backslash_pos[1]) && backslash_pos[1] != delim) {
249 return -1;
250 }
251
252 ptr = backslash_pos + 1;
253 }
254
255 return 0;
256}

References ast_assert, and end.

Referenced by regexp_invalid().

◆ services_invalid()

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
servicesThe services string parsed from a NAPTR record
services_sizeThe size of the services string
Return values
0Services are valid
-1Services are invalid

Definition at line 130 of file dns_naptr.c.

131{
132 const char *current_pos = services;
133 const char *end_of_services = services + services_size;
134
135 if (services_size == 0) {
136 return 0;
137 }
138
139 /* Services are broken into sections divided by a + sign. Each section
140 * must start with an alphabetic character, and then can only contain
141 * alphanumeric characters. The size of any section is limited to
142 * 32 characters
143 */
144 while (1) {
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;
147 int i;
148
149 if (!isalpha(current_pos[0])) {
150 return -1;
151 }
152
153 if (current_size > 32) {
154 return -1;
155 }
156
157 for (i = 1; i < current_size; ++i) {
158 if (!isalnum(current_pos[i])) {
159 return -1;
160 }
161 }
162
163 if (!plus_pos) {
164 break;
165 }
166 current_pos = plus_pos + 1;
167 }
168
169 return 0;
170}

Referenced by dns_naptr_alloc().