Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Data Structures | Functions | Variables
acl.c File Reference

Various sorts of access control. More...

#include "asterisk.h"
#include "asterisk/network.h"
#include <ifaddrs.h>
#include "asterisk/acl.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/srv.h"
#include "asterisk/cli.h"
Include dependency graph for acl.c:

Go to the source code of this file.

Data Structures

struct  dscp_codepoint
 

Functions

static int acl_new (struct ast_acl **pointer, const char *name)
 
static struct ast_haappend_ha_core (const char *sense, const char *stuff, struct ast_ha *path, int *error, int port_flags)
 
int ast_acl_list_is_empty (struct ast_acl_list *acl_list)
 Determines if an ACL is empty or if it contains entries. More...
 
void ast_acl_output (int fd, struct ast_acl_list *acl_list, const char *prefix)
 output an ACL to the provided fd More...
 
void ast_append_acl (const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
 Add a rule to an ACL struct. More...
 
struct ast_haast_append_ha (const char *sense, const char *stuff, struct ast_ha *path, int *error)
 Add a new rule to a list of HAs. More...
 
struct ast_haast_append_ha_with_port (const char *sense, const char *stuff, struct ast_ha *path, int *error)
 Add a new rule with optional port to a list of HAs. More...
 
enum ast_acl_sense ast_apply_acl (struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *purpose)
 Apply a set of rules to a given IP address. More...
 
static enum ast_acl_sense ast_apply_acl_internal (struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *log_prefix)
 
enum ast_acl_sense ast_apply_acl_nolog (struct ast_acl_list *acl_list, const struct ast_sockaddr *addr)
 Apply a set of rules to a given IP address, don't log failure. More...
 
enum ast_acl_sense ast_apply_ha (const struct ast_ha *ha, const struct ast_sockaddr *addr)
 Apply a set of rules to a given IP address. More...
 
void ast_copy_ha (const struct ast_ha *from, struct ast_ha *to)
 Copy the contents of one HA to another. More...
 
struct ast_acl_listast_duplicate_acl_list (struct ast_acl_list *original)
 Duplicates the contests of a list of lists of host access rules. More...
 
static struct ast_haast_duplicate_ha (struct ast_ha *original)
 
struct ast_haast_duplicate_ha_list (struct ast_ha *original)
 Duplicate the contents of a list of host access rules. More...
 
int ast_find_ourip (struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
 Find our IP address. More...
 
struct ast_acl_listast_free_acl_list (struct ast_acl_list *acl_list)
 Free a list of ACLs. More...
 
void ast_free_ha (struct ast_ha *ha)
 Free a list of HAs. More...
 
int ast_get_ip (struct ast_sockaddr *addr, const char *hostname)
 Get the IP address given a hostname. More...
 
int ast_get_ip_or_srv (struct ast_sockaddr *addr, const char *hostname, const char *service)
 Get the IP address given a hostname and optional service. More...
 
void ast_ha_join (const struct ast_ha *ha, struct ast_str **buf)
 Convert HAs to a comma separated string value. More...
 
void ast_ha_join_cidr (const struct ast_ha *ha, struct ast_str **buf)
 Convert HAs to a comma separated string value using CIDR notation. More...
 
void ast_ha_output (int fd, const struct ast_ha *ha, const char *prefix)
 output an HA to the provided fd More...
 
int ast_ouraddrfor (const struct ast_sockaddr *them, struct ast_sockaddr *us)
 Get our local IP address when contacting a remote host. More...
 
int ast_str2cos (const char *value, unsigned int *cos)
 Convert a string to the appropriate COS value. More...
 
int ast_str2tos (const char *value, unsigned int *tos)
 Convert a string to the appropriate TOS value. More...
 
const char * ast_tos2str (unsigned int tos)
 Convert a TOS value into its string representation. More...
 
static void debug_ha_sense_appended (struct ast_ha *ha)
 
static int get_local_address (struct ast_sockaddr *ourip)
 
static int parse_cidr_mask (struct ast_sockaddr *addr, int is_v4, const char *mask_str)
 Parse a netmask in CIDR notation. More...
 
static int resolve_first (struct ast_sockaddr *addr, const char *name, int flag, int family)
 
static void score_address (const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
 

Variables

static const struct dscp_codepoint dscp_pool1 []
 

Detailed Description

Various sorts of access control.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file acl.c.

Function Documentation

◆ acl_new()

static int acl_new ( struct ast_acl **  pointer,
const char *  name 
)
static

Definition at line 304 of file acl.c.

304 {
305 struct ast_acl *acl;
306 if (!(acl = ast_calloc(1, sizeof(*acl)))) {
307 return 1;
308 }
309
310 *pointer = acl;
312 return 0;
313}
#define ACL_NAME_LENGTH
Definition: acl.h:59
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static const char name[]
Definition: format_mp3.c:68
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Definition: test_acl.c:111
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67
struct ast_ha * acl
Definition: acl.h:68

References ast_acl::acl, ACL_NAME_LENGTH, ast_calloc, ast_copy_string(), and name.

Referenced by ast_append_acl(), and ast_duplicate_acl_list().

◆ append_ha_core()

static struct ast_ha * append_ha_core ( const char *  sense,
const char *  stuff,
struct ast_ha path,
int *  error,
int  port_flags 
)
static

Definition at line 575 of file acl.c.

576{
577 struct ast_ha *ha;
578 struct ast_ha *prev = NULL;
579 struct ast_ha *ret;
580 char *tmp, *list = ast_strdupa(stuff ?: "");
581 char *address = NULL, *mask = NULL;
582 int addr_is_v4;
583 int allowing = strncasecmp(sense, "p", 1) ? AST_SENSE_DENY : AST_SENSE_ALLOW;
584
585 ret = path;
586 while (path) {
587 prev = path;
588 path = path->next;
589 }
590
591 while ((tmp = strsep(&list, ","))) {
592 uint16_t save_port;
593
594 if (!(ha = ast_calloc(1, sizeof(*ha)))) {
595 if (error) {
596 *error = 1;
597 }
598 return ret;
599 }
600
601 address = strsep(&tmp, "/");
602 if (!address) {
603 address = tmp;
604 } else {
605 mask = tmp;
606 }
607
608 if (*address == '!') {
609 ha->sense = (allowing == AST_SENSE_DENY) ? AST_SENSE_ALLOW : AST_SENSE_DENY;
610 address++;
611 } else {
612 ha->sense = allowing;
613 }
614
615 if (!ast_sockaddr_parse(&ha->addr, address, port_flags)) {
616 ast_log(LOG_WARNING, "Invalid IP address: %s\n", address);
617 ast_free_ha(ha);
618 if (error) {
619 *error = 1;
620 }
621 return ret;
622 }
623
624 /* Be pedantic and zero out the port if we don't want it */
625 if ((port_flags & PARSE_PORT_MASK) == PARSE_PORT_FORBID) {
627 }
628
629 /* If someone specifies an IPv4-mapped IPv6 address,
630 * we just convert this to an IPv4 ACL
631 */
632 if (ast_sockaddr_ipv4_mapped(&ha->addr, &ha->addr)) {
633 ast_log(LOG_NOTICE, "IPv4-mapped ACL network address specified. "
634 "Converting to an IPv4 ACL network address.\n");
635 }
636
637 addr_is_v4 = ast_sockaddr_is_ipv4(&ha->addr);
638
639 if (!mask) {
640 parse_cidr_mask(&ha->netmask, addr_is_v4, addr_is_v4 ? "32" : "128");
641 } else if (strchr(mask, ':') || strchr(mask, '.')) {
642 int mask_is_v4;
643 /* Mask is of x.x.x.x or x:x:x:x:x:x:x:x variety */
644 if (!ast_sockaddr_parse(&ha->netmask, mask, PARSE_PORT_FORBID)) {
645 ast_log(LOG_WARNING, "Invalid netmask: %s\n", mask);
646 ast_free_ha(ha);
647 if (error) {
648 *error = 1;
649 }
650 return ret;
651 }
652 /* If someone specifies an IPv4-mapped IPv6 netmask,
653 * we just convert this to an IPv4 ACL
654 */
655 if (ast_sockaddr_ipv4_mapped(&ha->netmask, &ha->netmask)) {
656 ast_log(LOG_NOTICE, "IPv4-mapped ACL netmask specified. "
657 "Converting to an IPv4 ACL netmask.\n");
658 }
659 mask_is_v4 = ast_sockaddr_is_ipv4(&ha->netmask);
660 if (addr_is_v4 ^ mask_is_v4) {
661 ast_log(LOG_WARNING, "Address and mask are not using same address scheme.\n");
662 ast_free_ha(ha);
663 if (error) {
664 *error = 1;
665 }
666 return ret;
667 }
668 } else if (parse_cidr_mask(&ha->netmask, addr_is_v4, mask)) {
669 ast_log(LOG_WARNING, "Invalid CIDR netmask: %s\n", mask);
670 ast_free_ha(ha);
671 if (error) {
672 *error = 1;
673 }
674 return ret;
675 }
676
677 /* ast_sockaddr_apply_netmask() does not preserve the port, so we need to save and
678 * restore it */
679 save_port = ast_sockaddr_port(&ha->addr);
680
681 if (ast_sockaddr_apply_netmask(&ha->addr, &ha->netmask, &ha->addr)) {
682 /* This shouldn't happen because ast_sockaddr_parse would
683 * have failed much earlier on an unsupported address scheme
684 */
685 char *failmask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
686 char *failaddr = ast_strdupa(ast_sockaddr_stringify(&ha->addr));
687 ast_log(LOG_WARNING, "Unable to apply netmask %s to address %s\n", failmask, failaddr);
688 ast_free_ha(ha);
689 if (error) {
690 *error = 1;
691 }
692 return ret;
693 }
694
695 ast_sockaddr_set_port(&ha->addr, save_port);
696
697 if (prev) {
698 prev->next = ha;
699 } else {
700 ret = ha;
701 }
702 prev = ha;
703
704 if (DEBUG_ATLEAST(3)) {
706 }
707 }
708
709 return ret;
710}
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
static int parse_cidr_mask(struct ast_sockaddr *addr, int is_v4, const char *mask_str)
Parse a netmask in CIDR notation.
Definition: acl.c:381
static void debug_ha_sense_appended(struct ast_ha *ha)
Definition: acl.c:565
@ AST_SENSE_ALLOW
Definition: acl.h:38
@ AST_SENSE_DENY
Definition: acl.h:37
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
char * address
Definition: f2c.h:59
char * strsep(char **str, const char *delims)
#define DEBUG_ATLEAST(level)
#define LOG_NOTICE
#define LOG_WARNING
int ast_sockaddr_ipv4_mapped(const struct ast_sockaddr *addr, struct ast_sockaddr *ast_mapped)
Convert an IPv4-mapped IPv6 address into an IPv4 address.
Definition: netsock2.c:37
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
int ast_sockaddr_apply_netmask(const struct ast_sockaddr *addr, const struct ast_sockaddr *netmask, struct ast_sockaddr *result)
Apply a netmask to an address and store the result in a separate structure.
Definition: netsock2.c:357
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
#define NULL
Definition: resample.c:96
internal representation of ACL entries In principle user applications would have no need for this,...
Definition: acl.h:51
struct ast_sockaddr addr
Definition: acl.h:53
struct ast_sockaddr netmask
Definition: acl.h:54
struct ast_ha * next
Definition: acl.h:56
enum ast_acl_sense sense
Definition: acl.h:55
int error(const char *format,...)
Definition: utils/frame.c:999

References ast_ha::addr, ast_calloc, ast_free_ha(), ast_log, AST_SENSE_ALLOW, AST_SENSE_DENY, ast_sockaddr_apply_netmask(), ast_sockaddr_ipv4_mapped(), ast_sockaddr_is_ipv4(), ast_sockaddr_parse(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdupa, DEBUG_ATLEAST, debug_ha_sense_appended(), error(), LOG_NOTICE, LOG_WARNING, ast_ha::netmask, ast_ha::next, NULL, parse_cidr_mask(), PARSE_PORT_FORBID, PARSE_PORT_MASK, ast_ha::sense, strsep(), and tmp().

Referenced by ast_append_ha(), and ast_append_ha_with_port().

◆ ast_acl_list_is_empty()

int ast_acl_list_is_empty ( struct ast_acl_list acl_list)

Determines if an ACL is empty or if it contains entries.

Parameters
acl_listThe ACL list being checked
Return values
0the list is not empty
1the list is empty

Definition at line 540 of file acl.c.

541{
542 struct ast_acl *head;
543
544 if (!acl_list) {
545 return 1;
546 }
547
548 AST_LIST_LOCK(acl_list);
549 head = AST_LIST_FIRST(acl_list);
550 AST_LIST_UNLOCK(acl_list);
551
552 if (head) {
553 return 0;
554 }
555
556 return 1;
557}
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421

References AST_LIST_FIRST, AST_LIST_LOCK, and AST_LIST_UNLOCK.

Referenced by acl_to_str(), apply_acl(), apply_contact_acl(), apply_endpoint_acl(), apply_endpoint_contact_acl(), contact_acl_to_str(), curl_open_socket_cb(), handle_cli_iax2_show_peer(), handle_cli_iax2_show_users(), and handle_showmanager().

◆ ast_acl_output()

void ast_acl_output ( int  fd,
struct ast_acl_list acl,
const char *  prefix 
)

output an ACL to the provided fd

This function can be used centrally to output HAs as used in ACLs from other modules. It follows the format as originally used for named ACLs in named_acl.c.

Parameters
fdThe file-descriptor to which to output the ACL.
aclThe ACL to output.
prefixIf you need a specific prefix output on each line, give it here, may be NULL.
Since
13.33.0, 16.10.0, 17.4.0

Definition at line 1098 of file acl.c.

1099{
1100 struct ast_acl *acl;
1101
1102 AST_LIST_LOCK(acl_list);
1103 AST_LIST_TRAVERSE(acl_list, acl, list) {
1104 ast_cli(fd, "%sACL: %s%s\n---------------------------------------------\n",
1105 prefix ?: "", ast_strlen_zero(acl->name) ? "(unnamed)" : acl->name,
1106 acl->is_realtime ? " (realtime)" : "");
1107
1108 ast_ha_output(fd, acl->acl, prefix);
1109 }
1110 AST_LIST_UNLOCK(acl_list);
1111
1112}
void ast_ha_output(int fd, const struct ast_ha *ha, const char *prefix)
output an HA to the provided fd
Definition: acl.c:1086
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static char prefix[MAX_PREFIX]
Definition: http.c:144
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
struct ast_acl::@180 list

References ast_acl::acl, ast_cli(), ast_ha_output(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_acl::list, and prefix.

Referenced by handle_showmanager().

◆ ast_append_acl()

void ast_append_acl ( const char *  sense,
const char *  stuff,
struct ast_acl_list **  path,
int *  error,
int *  named_acl_flag 
)

Add a rule to an ACL struct.

This adds a named ACL or an ACL rule to an ast_acl container. It works in a similar way to ast_append_ha.

Parameters
senseCan be any among "permit", "deny", or "acl" this controls whether the rule being added will simply modify the unnamed ACL at the head of the list or if a new named ACL will be added to that ast_acl.
stuffIf sense is 'permit'/'deny', this is the ip address and subnet mask separated with a '/' like in ast_append ha. If it sense is 'acl', then this will be the name of the ACL being appended to the container.
pathAddress of the ACL list being appended
[out]errorThe int that error points to will be set to 1 if an error occurs.
[out]named_acl_flagThis will raise a flag under certain conditions to indicate that a named ACL has been added by this operation. This may be used to indicate that an event subscription should be made against the named ACL subsystem. Note: This flag may be raised by this function, but it will never be lowered by it.

Definition at line 429 of file acl.c.

430{
431 struct ast_acl *acl = NULL;
432 struct ast_acl *current;
433 struct ast_acl_list *working_list;
434
435 char *tmp, *list;
436
437 /* If the ACL list is currently uninitialized, it must be initialized. */
438 if (*path == NULL) {
439 struct ast_acl_list *list;
440 list = ast_calloc(1, sizeof(*list));
441 if (!list) {
442 /* Allocation Error */
443 if (error) {
444 *error = 1;
445 }
446 return;
447 }
448
449 AST_LIST_HEAD_INIT(list);
450 *path = list;
451 }
452
453 working_list = *path;
454
455 AST_LIST_LOCK(working_list);
456
457 /* First we need to determine if we will need to add a new ACL node or if we can use an existing one. */
458 if (strncasecmp(sense, "a", 1)) {
459 /* The first element in the path should be the unnamed, base ACL. If that's the case, we use it. If not,
460 * we have to make one and link it up appropriately. */
461 current = AST_LIST_FIRST(working_list);
462
463 if (!current || !ast_strlen_zero(current->name)) {
464 if (acl_new(&acl, "")) {
465 if (error) {
466 *error = 1;
467 }
468 AST_LIST_UNLOCK(working_list);
469 return;
470 }
471 // Need to INSERT the ACL at the head here.
472 AST_LIST_INSERT_HEAD(working_list, acl, list);
473 } else {
474 /* If the first element was already the unnamed base ACL, we just use that one. */
475 acl = current;
476 }
477
478 /* With the proper ACL set for modification, we can just pass this off to the ast_ha append function. */
479 acl->acl = ast_append_ha(sense, stuff, acl->acl, error);
480
481 AST_LIST_UNLOCK(working_list);
482 return;
483 }
484
485 /* We are in ACL append mode, so we know we'll be adding one or more named ACLs. */
486 list = ast_strdupa(stuff);
487
488 while ((tmp = strsep(&list, ","))) {
489 struct ast_ha *named_ha;
490 int already_included = 0;
491
492 /* Remove leading whitespace from the string in case the user put spaces between items */
494
495 /* The first step is to check for a duplicate */
496 AST_LIST_TRAVERSE(working_list, current, list) {
497 if (!strcasecmp(current->name, tmp)) { /* ACL= */
498 /* Inclusion of the same ACL multiple times isn't a catastrophic error, but it will raise the error flag and skip the entry. */
499 ast_log(LOG_ERROR, "Named ACL '%s' occurs multiple times in ACL definition. "
500 "Please update your ACL configuration.\n", tmp);
501 if (error) {
502 *error = 1;
503 }
504 already_included = 1;
505 break;
506 }
507 }
508
509 if (already_included) {
510 continue;
511 }
512
513 if (acl_new(&acl, tmp)) {
514 /* This is a catastrophic allocation error and we'll return immediately if this happens. */
515 if (error) {
516 *error = 1;
517 }
518 AST_LIST_UNLOCK(working_list);
519 return;
520 }
521
522 /* Attempt to grab the Named ACL we are looking for. */
523 named_ha = ast_named_acl_find(tmp, &acl->is_realtime, &acl->is_invalid);
524
525 /* Set the ACL's ast_ha to the duplicated named ACL retrieved above. */
526 acl->acl = named_ha;
527
528 /* Raise the named_acl_flag since we are adding a named ACL to the ACL container. */
529 if (named_acl_flag) {
530 *named_acl_flag = 1;
531 }
532
533 /* Now insert the new ACL at the end of the list. */
534 AST_LIST_INSERT_TAIL(working_list, acl, list);
535 }
536
537 AST_LIST_UNLOCK(working_list);
538}
static int acl_new(struct ast_acl **pointer, const char *name)
Definition: acl.c:304
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
Definition: acl.c:712
struct ast_ha * ast_named_acl_find(const char *name, int *is_realtime, int *is_undefined)
Retrieve a named ACL.
Definition: named_acl.c:293
#define LOG_ERROR
#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_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
size_t current
Definition: main/cli.c:113
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Wrapper for an ast_acl linked list.
Definition: acl.h:76

References acl_new(), ast_append_ha(), ast_calloc, AST_LIST_FIRST, AST_LIST_HEAD_INIT, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_named_acl_find(), ast_skip_blanks(), ast_strdupa, ast_strlen_zero(), current, error(), LOG_ERROR, NULL, strsep(), and tmp().

Referenced by __init_manager(), acl_handler(), build_peer(), build_user(), endpoint_acl_handler(), rtp_reload(), and verification_apply().

◆ ast_append_ha()

struct ast_ha * ast_append_ha ( const char *  sense,
const char *  stuff,
struct ast_ha path,
int *  error 
)

Add a new rule to a list of HAs.

This adds the new host access rule to the end of the list whose head is specified by the path parameter. Rules are evaluated in a way such that if multiple rules apply to a single IP address/subnet mask, then the rule latest in the list will be used.

Parameters
senseEither "permit" or "deny" (Actually any 'p' word will result in permission, and any other word will result in denial)
stuffThe IP address and subnet mask, separated with a '/'. The subnet mask can either be in dotted-decimal format or in CIDR notation (i.e. 0-32).
pathThe head of the HA list to which we wish to append our new rule. If NULL is passed, then the new rule will become the head of the list
[out]errorThe integer error points to will be set non-zero if an error occurs
Returns
The head of the HA list

Definition at line 712 of file acl.c.

713{
714 return append_ha_core(sense, stuff, path, error, PARSE_PORT_FORBID);
715}
static struct ast_ha * append_ha_core(const char *sense, const char *stuff, struct ast_ha *path, int *error, int port_flags)
Definition: acl.c:575

References append_ha_core(), error(), PARSE_PORT_FORBID, and ast_ha::sense.

Referenced by acl_handler_fn(), add_calltoken_ignore(), ast_append_acl(), AST_TEST_DEFINE(), build_callno_limits(), build_device(), build_ha(), named_acl_find_realtime(), and transport_localnet_handler().

◆ ast_append_ha_with_port()

struct ast_ha * ast_append_ha_with_port ( const char *  sense,
const char *  stuff,
struct ast_ha path,
int *  error 
)

Add a new rule with optional port to a list of HAs.

Since
13.31.0, 16.8.0, 17.2.0

This adds the new host access rule to the end of the list whose head is specified by the path parameter. Rules are evaluated in a way such that if multiple rules apply to a single IP address/subnet mask, then the rule latest in the list will be used.

Parameters
senseEither "permit" or "deny" (Actually any 'p' word will result in permission, and any other word will result in denial)
stuffThe IP address and subnet mask, separated with a '/'. The subnet mask can either be in dotted-decimal format or in CIDR notation (i.e. 0-32). A port can be provided by placing it after the IP address, separated with a ':'.
pathThe head of the HA list to which we wish to append our new rule. If NULL is passed, then the new rule will become the head of the list
[out]errorThe integer error points to will be set non-zero if an error occurs
Returns
The head of the HA list

Definition at line 717 of file acl.c.

718{
719 return append_ha_core(sense, stuff, path, error, 0);
720}

References append_ha_core(), error(), and ast_ha::sense.

Referenced by ip_identify_match_handler(), ip_identify_match_host_lookup(), and pjsip_enable_logger_host().

◆ ast_apply_acl()

enum ast_acl_sense ast_apply_acl ( struct ast_acl_list acl_list,
const struct ast_sockaddr addr,
const char *  purpose 
)

Apply a set of rules to a given IP address.

Similar to the above, only uses an acl container, which is a whole slew of ast_ha lists. It runs ast_apply_ha on each of the ast_ha structs contained in the acl container. It will deny if any of the ast_ha lists fail, and it will pass only if all of the rules pass.

Parameters
acl_listThe head of the list of ACLs to evaluate
addrAn ast_sockaddr whose address is considered when matching rules
purposeContext for which the ACL is being applied - Establishes purpose of a notice when rejected
Return values
AST_SENSE_ALLOWThe IP address passes our ACLs
AST_SENSE_DENYThe IP address fails our ACLs

Definition at line 799 of file acl.c.

799 {
800 return ast_apply_acl_internal(acl_list, addr, purpose ?: "");
801}
static enum ast_acl_sense ast_apply_acl_internal(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *log_prefix)
Definition: acl.c:757

References ast_apply_acl_internal().

Referenced by apply_acl(), apply_contact_acl(), apply_endpoint_acl(), apply_endpoint_contact_acl(), auth_http_callback(), authenticate(), check_access(), curl_open_socket_cb(), and register_verify().

◆ ast_apply_acl_internal()

static enum ast_acl_sense ast_apply_acl_internal ( struct ast_acl_list acl_list,
const struct ast_sockaddr addr,
const char *  log_prefix 
)
static

Definition at line 757 of file acl.c.

758{
759 struct ast_acl *acl;
760
761 /* If the list is NULL, there are no rules, so we'll allow automatically. */
762 if (!acl_list) {
763 return AST_SENSE_ALLOW;
764 }
765
766 AST_LIST_LOCK(acl_list);
767
768 AST_LIST_TRAVERSE(acl_list, acl, list) {
769 if (acl->is_invalid) {
770 /* In this case, the baseline ACL shouldn't ever trigger this, but if that somehow happens, it'll still be shown. */
771 if (log_prefix) {
772 ast_log(LOG_WARNING, "%sRejecting '%s' due to use of an invalid ACL '%s'.\n",
773 log_prefix, ast_sockaddr_stringify_addr(addr),
774 ast_strlen_zero(acl->name) ? "(BASELINE)" : acl->name);
775 }
776 AST_LIST_UNLOCK(acl_list);
777 return AST_SENSE_DENY;
778 }
779
780 if (acl->acl) {
781 if (ast_apply_ha(acl->acl, addr) == AST_SENSE_DENY) {
782 if (log_prefix) {
783 ast_log(LOG_NOTICE, "%sRejecting '%s' due to a failure to pass ACL '%s'\n",
784 log_prefix, ast_sockaddr_stringify_addr(addr),
785 ast_strlen_zero(acl->name) ? "(BASELINE)" : acl->name);
786 }
787 AST_LIST_UNLOCK(acl_list);
788 return AST_SENSE_DENY;
789 }
790 }
791 }
792
793 AST_LIST_UNLOCK(acl_list);
794
795 return AST_SENSE_ALLOW;
796}
enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address.
Definition: acl.c:807
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition: netsock2.h:286

References ast_acl::acl, ast_apply_ha(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, AST_SENSE_ALLOW, AST_SENSE_DENY, ast_sockaddr_stringify_addr(), ast_strlen_zero(), ast_acl::list, LOG_NOTICE, and LOG_WARNING.

Referenced by ast_apply_acl(), and ast_apply_acl_nolog().

◆ ast_apply_acl_nolog()

enum ast_acl_sense ast_apply_acl_nolog ( struct ast_acl_list acl_list,
const struct ast_sockaddr addr 
)

Apply a set of rules to a given IP address, don't log failure.

Exactly like ast_apply_acl, except that it will never log anything.

Parameters
acl_listThe head of the list of ACLs to evaluate
addrAn ast_sockaddr whose address is considered when matching rules
Return values
AST_SENSE_ALLOWThe IP address passes our ACLs
AST_SENSE_DENYThe IP address fails our ACLs

Definition at line 803 of file acl.c.

803 {
804 return ast_apply_acl_internal(acl_list, addr, NULL);
805}

References ast_apply_acl_internal(), and NULL.

◆ ast_apply_ha()

enum ast_acl_sense ast_apply_ha ( const struct ast_ha ha,
const struct ast_sockaddr addr 
)

Apply a set of rules to a given IP address.

The list of host access rules is traversed, beginning with the input rule. If the IP address given matches a rule, the "sense" of that rule is used as the return value. Note that if an IP address matches multiple rules that the last one matched will be the one whose sense will be returned.

Parameters
haThe head of the list of host access rules to follow
addrAn ast_sockaddr whose address is considered when matching rules
Return values
AST_SENSE_ALLOWThe IP address passes our ACL
AST_SENSE_DENYThe IP address fails our ACL

Definition at line 807 of file acl.c.

808{
809 /* Start optimistic */
811 const struct ast_ha *current_ha;
812
813 for (current_ha = ha; current_ha; current_ha = current_ha->next) {
814 struct ast_sockaddr result;
815 struct ast_sockaddr mapped_addr;
816 const struct ast_sockaddr *addr_to_use;
817 uint16_t save_port;
818#if 0 /* debugging code */
819 char iabuf[INET_ADDRSTRLEN];
820 char iabuf2[INET_ADDRSTRLEN];
821 /* DEBUG */
822 ast_copy_string(iabuf, ast_sockaddr_stringify(addr), sizeof(iabuf));
823 ast_copy_string(iabuf2, ast_sockaddr_stringify(&current_ha->addr), sizeof(iabuf2));
824 ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2);
825#endif
826 if (ast_sockaddr_is_ipv4(&current_ha->addr)) {
827 if (ast_sockaddr_is_ipv6(addr)) {
828 if (ast_sockaddr_is_ipv4_mapped(addr)) {
829 /* IPv4 ACLs apply to IPv4-mapped addresses */
830 if (!ast_sockaddr_ipv4_mapped(addr, &mapped_addr)) {
831 ast_log(LOG_ERROR, "%s provided to ast_sockaddr_ipv4_mapped could not be converted. That shouldn't be possible.\n",
833 continue;
834 }
835 addr_to_use = &mapped_addr;
836 } else {
837 /* An IPv4 ACL does not apply to an IPv6 address */
838 continue;
839 }
840 } else {
841 /* Address is IPv4 and ACL is IPv4. No biggie */
842 addr_to_use = addr;
843 }
844 } else {
846 addr_to_use = addr;
847 } else {
848 /* Address is IPv4 or IPv4 mapped but ACL is IPv6. Skip */
849 continue;
850 }
851 }
852
853 /* ast_sockaddr_apply_netmask() does not preserve the port, so we need to save and
854 * restore it */
855 save_port = ast_sockaddr_port(addr_to_use);
856
857 /* For each rule, if this address and the netmask = the net address
858 apply the current rule */
859 if (ast_sockaddr_apply_netmask(addr_to_use, &current_ha->netmask, &result)) {
860 /* Unlikely to happen since we know the address to be IPv4 or IPv6 */
861 continue;
862 }
863
864 ast_sockaddr_set_port(&result, save_port);
865
866 if (!ast_sockaddr_cmp_addr(&result, &current_ha->addr)
867 && (!ast_sockaddr_port(&current_ha->addr)
868 || ast_sockaddr_port(&current_ha->addr) == ast_sockaddr_port(&result))) {
869 res = current_ha->sense;
870 }
871 }
872 return res;
873}
ast_acl_sense
Definition: acl.h:36
static PGresult * result
Definition: cel_pgsql.c:84
#define ast_debug(level,...)
Log a DEBUG message.
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
Definition: netsock2.c:413
int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
Determine if this is an IPv4-mapped IPv6 address.
Definition: netsock2.c:507
Socket address structure.
Definition: netsock2.h:97

References ast_ha::addr, ast_copy_string(), ast_debug, ast_log, AST_SENSE_ALLOW, ast_sockaddr_apply_netmask(), ast_sockaddr_cmp_addr(), ast_sockaddr_ipv4_mapped(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv4_mapped(), ast_sockaddr_is_ipv6(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), LOG_ERROR, ast_ha::netmask, ast_ha::next, result, and ast_ha::sense.

Referenced by ast_apply_acl_internal(), AST_TEST_DEFINE(), ip_identify_match_check(), ip_identify_match_host_lookup(), and pjsip_log_test_filter().

◆ ast_copy_ha()

void ast_copy_ha ( const struct ast_ha from,
struct ast_ha to 
)

Copy the contents of one HA to another.

This copies the internals of the 'from' HA to the 'to' HA. It is important that the 'to' HA has been allocated prior to calling this function

Parameters
fromSource HA to copy
toDestination HA to copy to

Definition at line 255 of file acl.c.

256{
257 ast_sockaddr_copy(&to->addr, &from->addr);
258 ast_sockaddr_copy(&to->netmask, &from->netmask);
259 to->sense = from->sense;
260}
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition: netsock2.h:167

References ast_ha::addr, ast_sockaddr_copy(), ast_ha::netmask, and ast_ha::sense.

Referenced by add_calltoken_ignore(), ast_duplicate_ha(), and build_callno_limits().

◆ ast_duplicate_acl_list()

struct ast_acl_list * ast_duplicate_acl_list ( struct ast_acl_list original)

Duplicates the contests of a list of lists of host access rules.

A deep copy of an ast_acl list is made (which in turn means a deep copy of each of the ast_ha structs contained within). The returned value is allocated on the heap and must be freed independently of the input paramater when finished.

Parameters
originalThe ast_acl_list to copy
Returns
The new duplicated ast_acl_list

Definition at line 315 of file acl.c.

316{
317 struct ast_acl_list *clone;
318 struct ast_acl *current_cursor;
319 struct ast_acl *current_clone;
320
321 /* Early return if we receive a duplication request for a NULL original. */
322 if (!original) {
323 return NULL;
324 }
325
326 if (!(clone = ast_calloc(1, sizeof(*clone)))) {
327 ast_log(LOG_ERROR, "Failed to allocate ast_acl_list struct while cloning an ACL\n");
328 return NULL;
329 }
330 AST_LIST_HEAD_INIT(clone);
331
332 AST_LIST_LOCK(original);
333
334 AST_LIST_TRAVERSE(original, current_cursor, list) {
335 if ((acl_new(&current_clone, current_cursor->name))) {
336 ast_log(LOG_ERROR, "Failed to allocate ast_acl struct while cloning an ACL.\n");
337 ast_free_acl_list(clone);
338 clone = NULL;
339 break;
340 }
341
342 /* Copy data from original ACL to clone ACL */
343 current_clone->acl = ast_duplicate_ha_list(current_cursor->acl);
344
345 current_clone->is_invalid = current_cursor->is_invalid;
346 current_clone->is_realtime = current_cursor->is_realtime;
347
348 AST_LIST_INSERT_TAIL(clone, current_clone, list);
349
350 if (current_cursor->acl && !current_clone->acl) {
351 /* Deal with failure after adding to clone so we don't have to free
352 * current_clone separately. */
353 ast_log(LOG_ERROR, "Failed to duplicate HA list while cloning ACL.\n");
354 ast_free_acl_list(clone);
355 clone = NULL;
356 break;
357 }
358 }
359
360 AST_LIST_UNLOCK(original);
361
362 return clone;
363}
struct ast_ha * ast_duplicate_ha_list(struct ast_ha *original)
Duplicate the contents of a list of host access rules.
Definition: acl.c:276
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl_list)
Free a list of ACLs.
Definition: acl.c:233
int is_invalid
Definition: acl.h:70
int is_realtime
Definition: acl.h:69
char name[ACL_NAME_LENGTH]
Definition: acl.h:71

References ast_acl::acl, acl_new(), ast_calloc, ast_duplicate_ha_list(), ast_free_acl_list(), AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_acl::is_invalid, ast_acl::is_realtime, ast_acl::list, LOG_ERROR, ast_acl::name, and NULL.

Referenced by vs_copy_cfg_common().

◆ ast_duplicate_ha()

static struct ast_ha * ast_duplicate_ha ( struct ast_ha original)
static

Definition at line 263 of file acl.c.

264{
265 struct ast_ha *new_ha;
266
267 if ((new_ha = ast_calloc(1, sizeof(*new_ha)))) {
268 /* Copy from original to new object */
269 ast_copy_ha(original, new_ha);
270 }
271
272 return new_ha;
273}
void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
Copy the contents of one HA to another.
Definition: acl.c:255

References ast_calloc, and ast_copy_ha().

Referenced by ast_duplicate_ha_list().

◆ ast_duplicate_ha_list()

struct ast_ha * ast_duplicate_ha_list ( struct ast_ha original)

Duplicate the contents of a list of host access rules.

A deep copy of all ast_has in the list is made. The returned value is allocated on the heap and must be freed independently of the input parameter when finished.

Parameters
originalThe ast_ha to copy
Returns
The head of the list of duplicated ast_has

Definition at line 276 of file acl.c.

277{
278 struct ast_ha *start = original;
279 struct ast_ha *ret = NULL;
280 struct ast_ha *current, *prev = NULL;
281
282 while (start) {
283 current = ast_duplicate_ha(start); /* Create copy of this object */
284 if (!current) {
285 ast_free_ha(ret);
286
287 return NULL;
288 }
289
290 if (prev) {
291 prev->next = current; /* Link previous to this object */
292 }
293
294 if (!ret) {
295 ret = current; /* Save starting point */
296 }
297
298 start = start->next; /* Go to next object */
299 prev = current; /* Save pointer to this object */
300 }
301 return ret; /* Return start of list */
302}
static struct ast_ha * ast_duplicate_ha(struct ast_ha *original)
Definition: acl.c:263

References ast_duplicate_ha(), ast_free_ha(), current, ast_ha::next, and NULL.

Referenced by ast_duplicate_acl_list(), and ast_named_acl_find().

◆ ast_find_ourip()

int ast_find_ourip ( struct ast_sockaddr ourip,
const struct ast_sockaddr bindaddr,
int  family 
)

Find our IP address.

This function goes through many iterations in an attempt to find our IP address. If any step along the way should fail, we move to the next item in the list. Here are the steps taken:

  • If bindaddr has a non-zero IP address, that is copied into ourip
  • We use a combination of gethostname and ast_gethostbyname to find our IP address.
  • We use ast_ouraddrfor with 198.41.0.4 as the destination IP address
  • We try some platform-specific socket operations to find the IP address
Parameters
[out]ouripOur IP address is written here when it is found
bindaddrA hint used for finding our IP. See the steps above for more details
familyOnly addresses of the given family will be returned. Use 0 or AST_SOCKADDR_UNSPEC to get addresses of all families.
Return values
0Success
-1Failure

Definition at line 1051 of file acl.c.

1052{
1053 char ourhost[MAXHOSTNAMELEN] = "";
1054 struct ast_sockaddr root;
1055 int res, port = ast_sockaddr_port(ourip);
1056
1057 /* just use the bind address if it is nonzero */
1060 ast_debug(3, "Attached to given IP address\n");
1061 return 0;
1062 }
1063 /* try to use our hostname */
1064 if (gethostname(ourhost, sizeof(ourhost) - 1)) {
1065 ast_log(LOG_WARNING, "Unable to get hostname\n");
1066 } else {
1067 if (resolve_first(ourip, ourhost, PARSE_PORT_FORBID, family) == 0) {
1068 /* reset port since resolve_first wipes this out */
1069 ast_sockaddr_set_port(ourip, port);
1070 return 0;
1071 }
1072 }
1073 ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
1074 /* A.ROOT-SERVERS.NET. */
1075 if (!resolve_first(&root, "A.ROOT-SERVERS.NET", PARSE_PORT_FORBID, 0) &&
1076 !ast_ouraddrfor(&root, ourip)) {
1077 /* reset port since resolve_first wipes this out */
1078 ast_sockaddr_set_port(ourip, port);
1079 return 0;
1080 }
1081 res = get_local_address(ourip);
1082 ast_sockaddr_set_port(ourip, port);
1083 return res;
1084}
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition: acl.c:1004
static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag, int family)
Definition: acl.c:875
static int get_local_address(struct ast_sockaddr *ourip)
Definition: acl.c:118
struct ast_sockaddr bindaddr
Definition: chan_ooh323.c:353
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
Definition: netsock2.c:534
#define MAXHOSTNAMELEN
Definition: network.h:69

References ast_debug, ast_log, ast_ouraddrfor(), ast_sockaddr_copy(), ast_sockaddr_is_any(), ast_sockaddr_port, ast_sockaddr_set_port, bindaddr, get_local_address(), LOG_WARNING, MAXHOSTNAMELEN, PARSE_PORT_FORBID, and resolve_first().

Referenced by ast_rtp_prop_set().

◆ ast_free_acl_list()

struct ast_acl_list * ast_free_acl_list ( struct ast_acl_list acl)

Free a list of ACLs.

Given the head of a list of ast_acl structs, it and all appended acl structs will be freed. This includes the ast_ha structs within the individual nodes.

Parameters
aclThe list of ACLs to free
Return values
NULL

Definition at line 233 of file acl.c.

234{
235 struct ast_acl *current;
236
237 if (!acl_list) {
238 return NULL;
239 }
240
241 AST_LIST_LOCK(acl_list);
242 while ((current = AST_LIST_REMOVE_HEAD(acl_list, list))) {
243 ast_free_ha(current->acl);
245 }
246 AST_LIST_UNLOCK(acl_list);
247
248 AST_LIST_HEAD_DESTROY(acl_list);
249 ast_free(acl_list);
250
251 return NULL;
252}
#define ast_free(a)
Definition: astmm.h:180
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:653
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833

References ast_free, ast_free_ha(), AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, current, ast_acl::list, and NULL.

Referenced by __init_manager(), acl_destroy(), ast_duplicate_acl_list(), build_peer(), build_user(), endpoint_destructor(), manager_free_user(), peer_destructor(), rtp_reload(), user_destructor(), vcfg_cleanup(), verification_apply(), and vs_copy_cfg_common().

◆ ast_free_ha()

void ast_free_ha ( struct ast_ha ha)

Free a list of HAs.

Given the head of a list of HAs, it and all appended HAs are freed

Parameters
haThe head of the list of HAs to free

Definition at line 222 of file acl.c.

223{
224 struct ast_ha *hal;
225 while (ha) {
226 hal = ha;
227 ha = ha->next;
228 ast_free(hal);
229 }
230}

References ast_free, and ast_ha::next.

Referenced by add_calltoken_ignore(), append_ha_core(), ast_duplicate_ha_list(), ast_free_acl_list(), AST_TEST_DEFINE(), build_callno_limits(), destroy_named_acl(), destroy_sip_transport_state(), ip_identify_destroy(), named_acl_find_realtime(), pjsip_disable_logger(), pjsip_enable_logger_host(), pjsip_logger_session_destroy(), test_item_destructor(), and transport_localnet_handler().

◆ ast_get_ip()

int ast_get_ip ( struct ast_sockaddr addr,
const char *  hostname 
)

Get the IP address given a hostname.

Similar in nature to ast_gethostbyname, except that instead of getting an entire hostent structure, you instead are given only the IP address inserted into a ast_sockaddr structure.

Parameters
addrThe IP address found. The address family is used as an input parameter to filter the returned addresses. If it is AST_AF_UNSPEC, both IPv4 and IPv6 addresses can be returned.
hostnameThe hostname to look up
Return values
0Success
-1Failure

Definition at line 999 of file acl.c.

1000{
1001 return ast_get_ip_or_srv(addr, hostname, NULL);
1002}
int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service)
Get the IP address given a hostname and optional service.
Definition: acl.c:896
static char hostname[MAXHOSTNAMELEN]
Definition: logger.c:119

References ast_get_ip_or_srv(), hostname, and NULL.

Referenced by build_peer(), peer_set_srcaddr(), setup_stunaddr(), and stun_monitor_request().

◆ ast_get_ip_or_srv()

int ast_get_ip_or_srv ( struct ast_sockaddr addr,
const char *  hostname,
const char *  service 
)

Get the IP address given a hostname and optional service.

If the service parameter is non-NULL, then an SRV lookup will be made by prepending the service to the hostname parameter, separated by a '.' For example, if hostname is "example.com" and service is "_sip._udp" then an SRV lookup will be done for "_sip._udp.example.com". If service is NULL, then this function acts exactly like a call to ast_get_ip.

Parameters
addrThe IP address found. The address family is used as an input parameter to filter the returned addresses. If it is 0, both IPv4 and IPv6 addresses can be returned.
hostnameThe hostname to look up
serviceA specific service provided by the host. A NULL service results in an A-record lookup instead of an SRV lookup
Return values
0Success
-1Failure

Definition at line 896 of file acl.c.

897{
898 char srv[256];
899 char host[256];
900 int srv_ret = 0;
901 int tportno;
902
903 if (service) {
904 snprintf(srv, sizeof(srv), "%s.%s", service, hostname);
905 if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, srv)) > 0) {
906 hostname = host;
907 }
908 }
909
910 if (resolve_first(addr, hostname, PARSE_PORT_FORBID, addr->ss.ss_family) != 0) {
911 return -1;
912 }
913
914 if (srv_ret > 0) {
915 ast_sockaddr_set_port(addr, tportno);
916 }
917
918 return 0;
919}
enum ast_cc_service_type service
Definition: ccss.c:383
int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
Lookup entry in SRV records Returns 1 if found, 0 if not found, -1 on hangup.
Definition: srv.c:260
struct sockaddr_storage ss
Definition: netsock2.h:98

References ast_get_srv(), ast_sockaddr_set_port, hostname, NULL, PARSE_PORT_FORBID, resolve_first(), service, and ast_sockaddr::ss.

Referenced by ast_get_ip(), create_addr(), dnsmgr_refresh(), and internal_dnsmgr_lookup().

◆ ast_ha_join()

void ast_ha_join ( const struct ast_ha ha,
struct ast_str **  buf 
)

Convert HAs to a comma separated string value.

Parameters
hathe starting ha head
bufstring buffer to convert data to

Definition at line 722 of file acl.c.

723{
724 for (; ha; ha = ha->next) {
725 const char *addr;
726
727 if (ast_sockaddr_port(&ha->addr)) {
728 addr = ast_sockaddr_stringify(&ha->addr);
729 } else {
731 }
732
733 ast_str_append(buf, 0, "%s%s/",
734 ha->sense == AST_SENSE_ALLOW ? "!" : "",
735 addr);
736 /* Separated to avoid duplicating stringified addresses. */
738 if (ha->next) {
739 ast_str_append(buf, 0, ",");
740 }
741 }
742}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139

References ast_ha::addr, AST_SENSE_ALLOW, ast_sockaddr_port, ast_sockaddr_stringify(), ast_sockaddr_stringify_addr(), ast_str_append(), buf, ast_ha::netmask, ast_ha::next, and ast_ha::sense.

Referenced by localnet_to_str(), and match_to_str().

◆ ast_ha_join_cidr()

void ast_ha_join_cidr ( const struct ast_ha ha,
struct ast_str **  buf 
)

Convert HAs to a comma separated string value using CIDR notation.

Parameters
hathe starting ha head
bufstring buffer to convert data to

Definition at line 744 of file acl.c.

745{
746 for (; ha; ha = ha->next) {
747 const char *addr = ast_sockaddr_stringify_addr(&ha->addr);
748 ast_str_append(buf, 0, "%s%s/%d",
749 ha->sense == AST_SENSE_ALLOW ? "!" : "",
750 addr, ast_sockaddr_cidr_bits(&ha->netmask));
751 if (ha->next) {
752 ast_str_append(buf, 0, ",");
753 }
754 }
755}
int ast_sockaddr_cidr_bits(const struct ast_sockaddr *sa)
Count the 1 bits in a netmask.
Definition: netsock2.c:130

References ast_ha::addr, AST_SENSE_ALLOW, ast_sockaddr_cidr_bits(), ast_sockaddr_stringify_addr(), ast_str_append(), buf, ast_ha::netmask, ast_ha::next, and ast_ha::sense.

◆ ast_ha_output()

void ast_ha_output ( int  fd,
const struct ast_ha ha,
const char *  prefix 
)

output an HA to the provided fd

This function can be used centrally to output HAs as used in ACLs from other modules. It follows the format as originally used for named ACLs in named_acl.c.

Parameters
fdThe file-descriptor to which to output the HA.
haThe HA to output.
prefixIf you need a specific prefix output on each line, give it here, may be NULL.
Since
13.33.0, 16.10.0, 17.4.0

Definition at line 1086 of file acl.c.

1087{
1088 char addr[AST_SOCKADDR_BUFLEN];
1089 char *mask;
1090 int index = 0;
1091 for (; ha; ha = ha->next, ++index) {
1092 strcpy(addr, ast_sockaddr_stringify_addr(&ha->addr));
1094 ast_cli(fd, "%s%3d: %s - %s/%s\n", prefix ?: "", index, ha->sense == AST_SENSE_ALLOW ? "allow" : " deny", addr, mask);
1095 }
1096}
#define AST_SOCKADDR_BUFLEN
Definition: netsock2.h:46

References ast_ha::addr, ast_cli(), AST_SENSE_ALLOW, AST_SOCKADDR_BUFLEN, ast_sockaddr_stringify_addr(), ast_ha::netmask, ast_ha::next, prefix, and ast_ha::sense.

Referenced by ast_acl_output(), cli_display_named_acl(), and print_acl().

◆ ast_ouraddrfor()

int ast_ouraddrfor ( const struct ast_sockaddr them,
struct ast_sockaddr us 
)

Get our local IP address when contacting a remote host.

This function will attempt to connect(2) to them over UDP using a source port of 5060. If the connect(2) call is successful, then we inspect the sockaddr_in output parameter of connect(2) to determine the IP address used to connect to them. This IP address is then copied into us.

Parameters
themThe IP address to which we wish to attempt to connect
[out]usThe source IP address used to connect to them
Return values
-1Failure
0Success

Definition at line 1004 of file acl.c.

1005{
1006 /*
1007 * We must create the errno string before creating the address
1008 * string because it could wipe out errno on the error return
1009 * paths.
1010 */
1011 const char *sock_err;
1012 int port;
1013 int s;
1014
1015 /* Preserve our original address port */
1016 port = ast_sockaddr_port(us);
1017
1018 s = socket(ast_sockaddr_is_ipv6(them) ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
1019 if (s < 0) {
1020 sock_err = ast_strdupa(strerror(errno));
1021 ast_log(LOG_ERROR, "Cannot create socket to %s: %s\n",
1022 ast_sockaddr_stringify_addr(them), sock_err);
1023 return -1;
1024 }
1025
1026 if (ast_connect(s, them)) {
1027 sock_err = ast_strdupa(strerror(errno));
1028 ast_log(LOG_WARNING, "Cannot connect to %s: %s\n",
1029 ast_sockaddr_stringify_addr(them), sock_err);
1030 close(s);
1031 return -1;
1032 }
1033 if (ast_getsockname(s, us)) {
1034 sock_err = ast_strdupa(strerror(errno));
1035 ast_log(LOG_WARNING, "Cannot get socket name for connection to %s: %s\n",
1036 ast_sockaddr_stringify_addr(them), sock_err);
1037 close(s);
1038 return -1;
1039 }
1040 close(s);
1041
1042 ast_sockaddr_set_port(us, port);
1043
1044 ast_debug(3, "For destination '%s', our source address is '%s'.\n",
1047
1048 return 0;
1049}
int errno
int ast_getsockname(int sockfd, struct ast_sockaddr *addr)
Wrapper around getsockname(2) that uses struct ast_sockaddr.
Definition: netsock2.c:600
int ast_connect(int sockfd, const struct ast_sockaddr *addr)
Wrapper around connect(2) that uses struct ast_sockaddr.
Definition: netsock2.c:595

References ast_connect(), ast_debug, ast_getsockname(), ast_log, ast_sockaddr_is_ipv6(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify_addr(), ast_strdupa, errno, LOG_ERROR, and LOG_WARNING.

Referenced by ast_find_ourip(), ast_rtp_remote_address_set(), and unicast_rtp_request().

◆ ast_str2cos()

int ast_str2cos ( const char *  value,
unsigned int *  cos 
)

Convert a string to the appropriate COS value.

Parameters
valueThe COS string to convert
[out]cosThe integer representation of that COS value
Return values
-1Failure
0Success

Definition at line 952 of file acl.c.

953{
954 int fval;
955
956 if (sscanf(value, "%30d", &fval) == 1) {
957 if (fval < 8) {
958 *cos = fval;
959 return 0;
960 }
961 }
962
963 return -1;
964}
unsigned int cos
Definition: chan_iax2.c:359
int value
Definition: syslog.c:37

References cos, and value.

Referenced by reload_config(), and set_config().

◆ ast_str2tos()

int ast_str2tos ( const char *  value,
unsigned int *  tos 
)

Convert a string to the appropriate TOS value.

Parameters
valueThe TOS string to convert
[out]tosThe integer representation of that TOS value
Return values
-1Failure
0Success

Definition at line 966 of file acl.c.

967{
968 int fval;
969 unsigned int x;
970
971 if (sscanf(value, "%30i", &fval) == 1) {
972 *tos = fval & 0xFF;
973 return 0;
974 }
975
976 for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
977 if (!strcasecmp(value, dscp_pool1[x].name)) {
978 *tos = dscp_pool1[x].space << 2;
979 return 0;
980 }
981 }
982
983 return -1;
984}
static const struct dscp_codepoint dscp_pool1[]
Definition: acl.c:928
unsigned int tos
Definition: chan_iax2.c:358
unsigned int space
Definition: acl.c:923
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, dscp_pool1, name, dscp_codepoint::space, tos, and value.

Referenced by iax_template_parse(), reload_config(), set_config(), tos_handler(), and transport_tos_handler().

◆ ast_tos2str()

const char * ast_tos2str ( unsigned int  tos)

Convert a TOS value into its string representation.

Parameters
tosThe TOS value to look up
Returns
The string equivalent of the TOS value

Definition at line 986 of file acl.c.

987{
988 unsigned int x;
989
990 for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
991 if (dscp_pool1[x].space == (tos >> 2)) {
992 return dscp_pool1[x].name;
993 }
994 }
995
996 return "unknown";
997}
char * name
Definition: acl.c:922

References ARRAY_LEN, dscp_pool1, dscp_codepoint::name, dscp_codepoint::space, and tos.

◆ debug_ha_sense_appended()

static void debug_ha_sense_appended ( struct ast_ha ha)
static

Definition at line 565 of file acl.c.

566{
567 const char *parsed_mask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
568
569 ast_log(LOG_DEBUG, "%s/%s sense %u appended to ACL\n",
571 parsed_mask,
572 ha->sense);
573}
#define LOG_DEBUG

References ast_ha::addr, ast_log, ast_sockaddr_stringify(), ast_strdupa, LOG_DEBUG, ast_ha::netmask, and ast_ha::sense.

Referenced by append_ha_core().

◆ get_local_address()

static int get_local_address ( struct ast_sockaddr ourip)
static

Definition at line 118 of file acl.c.

119{
120 int s, res = -1;
121#ifdef SOLARIS
122 struct lifreq *ifr = NULL;
123 struct lifnum ifn;
124 struct lifconf ifc;
125 struct sockaddr_in *sa;
126 char *buf = NULL;
127 int bufsz, x;
128#endif /* SOLARIS */
129#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
130 struct ifaddrs *ifap, *ifaphead;
131 int rtnerr;
132 const struct sockaddr_in *sin;
133#endif /* BSD_OR_LINUX */
134 struct in_addr best_addr;
135 int best_score = -100;
136 memset(&best_addr, 0, sizeof(best_addr));
137
138#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
139 rtnerr = getifaddrs(&ifaphead);
140 if (rtnerr) {
141 perror(NULL);
142 return -1;
143 }
144#endif /* BSD_OR_LINUX */
145
146 s = socket(AF_INET, SOCK_STREAM, 0);
147
148 if (s > 0) {
149#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
150 for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
151
152 if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) {
153 sin = (const struct sockaddr_in *) ifap->ifa_addr;
154 score_address(sin, &best_addr, &best_score);
155 res = 0;
156
157 if (best_score == 0) {
158 break;
159 }
160 }
161 }
162#endif /* BSD_OR_LINUX */
163
164 /* There is no reason whatsoever that this shouldn't work on Linux or BSD also. */
165#ifdef SOLARIS
166 /* Get a count of interfaces on the machine */
167 ifn.lifn_family = AF_INET;
168 ifn.lifn_flags = 0;
169 ifn.lifn_count = 0;
170 if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
171 close(s);
172 return -1;
173 }
174
175 bufsz = ifn.lifn_count * sizeof(struct lifreq);
176 if (!(buf = ast_malloc(bufsz))) {
177 close(s);
178 return -1;
179 }
180 memset(buf, 0, bufsz);
181
182 /* Get a list of interfaces on the machine */
183 ifc.lifc_len = bufsz;
184 ifc.lifc_buf = buf;
185 ifc.lifc_family = AF_INET;
186 ifc.lifc_flags = 0;
187 if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
188 close(s);
189 ast_free(buf);
190 return -1;
191 }
192
193 for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) {
194 sa = (struct sockaddr_in *)&(ifr->lifr_addr);
195 score_address(sa, &best_addr, &best_score);
196 res = 0;
197
198 if (best_score == 0) {
199 break;
200 }
201 }
202
203 ast_free(buf);
204#endif /* SOLARIS */
205
206 close(s);
207 }
208#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
209 freeifaddrs(ifaphead);
210#endif /* BSD_OR_LINUX */
211
212 if (res == 0 && ourip) {
214 ourip->ss.ss_family = AF_INET;
215 ((struct sockaddr_in *)&ourip->ss)->sin_addr = best_addr;
216 }
217 return res;
218}
static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
Definition: acl.c:59
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:138

References ast_free, ast_malloc, ast_sockaddr_setnull(), buf, NULL, score_address(), and ast_sockaddr::ss.

Referenced by ast_find_ourip().

◆ parse_cidr_mask()

static int parse_cidr_mask ( struct ast_sockaddr addr,
int  is_v4,
const char *  mask_str 
)
static

Parse a netmask in CIDR notation.

For a mask of an IPv4 address, this should be a number between 0 and 32. For a mask of an IPv6 address, this should be a number between 0 and 128. This function creates an IPv6 ast_sockaddr from the given netmask. For masks of IPv4 addresses, this is accomplished by adding 96 to the original netmask.

Parameters
[out]addrThe ast_sockaddr produced from the CIDR netmask
is_v4Tells if the address we are masking is IPv4.
mask_strThe CIDR mask to convert
Return values
-1Failure
0Success

Definition at line 381 of file acl.c.

382{
383 int mask;
384
385 if (sscanf(mask_str, "%30d", &mask) != 1) {
386 return -1;
387 }
388
389 if (is_v4) {
390 struct sockaddr_in sin;
391 if (mask < 0 || mask > 32) {
392 return -1;
393 }
394 memset(&sin, 0, sizeof(sin));
395 sin.sin_family = AF_INET;
396 /* If mask is 0, then we already have the
397 * appropriate all 0s address in sin from
398 * the above memset.
399 */
400 if (mask != 0) {
401 sin.sin_addr.s_addr = htonl(0xFFFFFFFF << (32 - mask));
402 }
403 ast_sockaddr_from_sin(addr, &sin);
404 } else {
405 struct sockaddr_in6 sin6;
406 int i;
407 if (mask < 0 || mask > 128) {
408 return -1;
409 }
410 memset(&sin6, 0, sizeof(sin6));
411 sin6.sin6_family = AF_INET6;
412 for (i = 0; i < 4; ++i) {
413 /* Once mask reaches 0, we don't have
414 * to explicitly set anything anymore
415 * since sin6 was zeroed out already
416 */
417 if (mask > 0) {
418 V6_WORD(&sin6, i) = htonl(0xFFFFFFFF << (mask < 32 ? (32 - mask) : 0));
419 mask -= mask < 32 ? mask : 32;
420 }
421 }
422 memcpy(&addr->ss, &sin6, sizeof(sin6));
423 addr->len = sizeof(sin6);
424 }
425
426 return 0;
427}
#define V6_WORD(sin6, index)
Isolate a 32-bit section of an IPv6 address.
Definition: netsock2.h:77
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:778
socklen_t len
Definition: netsock2.h:99

References ast_sockaddr_from_sin, ast_sockaddr::len, ast_sockaddr::ss, and V6_WORD.

Referenced by append_ha_core().

◆ resolve_first()

static int resolve_first ( struct ast_sockaddr addr,
const char *  name,
int  flag,
int  family 
)
static

Definition at line 875 of file acl.c.

877{
878 struct ast_sockaddr *addrs;
879 int addrs_cnt;
880
881 addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family);
882 if (addrs_cnt > 0) {
883 if (addrs_cnt > 1) {
884 ast_debug(1, "Multiple addresses. Using the first only\n");
885 }
886 ast_sockaddr_copy(addr, &addrs[0]);
887 ast_free(addrs);
888 } else {
889 ast_log(LOG_WARNING, "Unable to lookup '%s'\n", name);
890 return -1;
891 }
892
893 return 0;
894}
long int flag
Definition: f2c.h:83
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition: netsock2.c:280

References ast_debug, ast_free, ast_log, ast_sockaddr_copy(), ast_sockaddr_resolve(), LOG_WARNING, and name.

Referenced by ast_find_ourip(), and ast_get_ip_or_srv().

◆ score_address()

static void score_address ( const struct sockaddr_in *  sin,
struct in_addr *  best_addr,
int *  best_score 
)
static
Note
Better score than a test network, but not quite as good as RFC 1918 address space. The reason is that some Linux distributions automatically configure a Zeroconf address before trying DHCP, so we want to prefer a DHCP lease to a Zeroconf address.

Definition at line 59 of file acl.c.

60{
61 const char *address;
62 int score;
63
64 address = ast_inet_ntoa(sin->sin_addr);
65
66 /* RFC 1700 alias for the local network */
67 if (address[0] == '0') {
68 score = -25;
69 /* RFC 1700 localnet */
70 } else if (strncmp(address, "127", 3) == 0) {
71 score = -20;
72 /* RFC 1918 non-public address space */
73 } else if (strncmp(address, "10.", 3) == 0) {
74 score = -5;
75 /* RFC 1918 non-public address space */
76 } else if (strncmp(address, "172", 3) == 0) {
77 /* 172.16.0.0 - 172.19.255.255, but not 172.160.0.0 - 172.169.255.255 */
78 if (address[4] == '1' && address[5] >= '6' && address[6] == '.') {
79 score = -5;
80 /* 172.20.0.0 - 172.29.255.255, but not 172.200.0.0 - 172.255.255.255 nor 172.2.0.0 - 172.2.255.255 */
81 } else if (address[4] == '2' && address[6] == '.') {
82 score = -5;
83 /* 172.30.0.0 - 172.31.255.255, but not 172.3.0.0 - 172.3.255.255 */
84 } else if (address[4] == '3' && (address[5] == '0' || address[5] == '1')) {
85 score = -5;
86 /* All other 172 addresses are public */
87 } else {
88 score = 0;
89 }
90 /* RFC 2544 Benchmark test range (198.18.0.0 - 198.19.255.255, but not 198.180.0.0 - 198.199.255.255) */
91 } else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.') {
92 score = -10;
93 /* RFC 1918 non-public address space */
94 } else if (strncmp(address, "192.168", 7) == 0) {
95 score = -5;
96 /* RFC 3330 Zeroconf network */
97 } else if (strncmp(address, "169.254", 7) == 0) {
98 /*!\note Better score than a test network, but not quite as good as RFC 1918
99 * address space. The reason is that some Linux distributions automatically
100 * configure a Zeroconf address before trying DHCP, so we want to prefer a
101 * DHCP lease to a Zeroconf address.
102 */
103 score = -10;
104 /* RFC 3330 Test network */
105 } else if (strncmp(address, "192.0.2.", 8) == 0) {
106 score = -15;
107 /* Every other address should be publically routable */
108 } else {
109 score = 0;
110 }
111
112 if (score > *best_score) {
113 *best_score = score;
114 memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr));
115 }
116}
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:928

References ast_inet_ntoa().

Referenced by get_local_address().

Variable Documentation

◆ dscp_pool1

const struct dscp_codepoint dscp_pool1[]
static

Definition at line 928 of file acl.c.

Referenced by ast_str2tos(), and ast_tos2str().