Asterisk - The Open Source Telephony Project  18.5.0
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 305 of file acl.c.

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

Referenced by ast_append_acl(), and ast_duplicate_acl_list().

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

◆ 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 576 of file acl.c.

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(), 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().

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

◆ 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
0- the list is not empty
1- the list is empty

Definition at line 541 of file acl.c.

References AST_LIST_FIRST, AST_LIST_LOCK, and AST_LIST_UNLOCK.

Referenced by _sip_show_peer(), _sip_show_peers_one(), acl_to_str(), apply_acl(), apply_contact_acl(), apply_endpoint_acl(), apply_endpoint_contact_acl(), contact_acl_to_str(), handle_cli_iax2_show_peer(), handle_cli_iax2_show_users(), handle_showmanager(), sip_show_user(), and sip_show_users().

542 {
543  struct ast_acl *head;
544 
545  if (!acl_list) {
546  return 1;
547  }
548 
549  AST_LIST_LOCK(acl_list);
550  head = AST_LIST_FIRST(acl_list);
551  AST_LIST_UNLOCK(acl_list);
552 
553  if (head) {
554  return 0;
555  }
556 
557  return 1;
558 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67

◆ 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 1099 of file acl.c.

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

Referenced by handle_showmanager().

1100 {
1101  struct ast_acl *acl;
1102 
1103  AST_LIST_LOCK(acl_list);
1104  AST_LIST_TRAVERSE(acl_list, acl, list) {
1105  ast_cli(fd, "%sACL: %s%s\n---------------------------------------------\n",
1106  prefix ?: "", ast_strlen_zero(acl->name) ? "(unnamed)" : acl->name,
1107  acl->is_realtime ? " (realtime)" : "");
1108 
1109  ast_ha_output(fd, acl->acl, prefix);
1110  }
1111  AST_LIST_UNLOCK(acl_list);
1112 
1113 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct ast_acl::@218 list
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char name[ACL_NAME_LENGTH]
Definition: acl.h:71
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ast_strlen_zero(foo)
Definition: strings.h:52
int is_realtime
Definition: acl.h:69
struct ast_ha * acl
Definition: acl.h:68
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67
void ast_ha_output(int fd, const struct ast_ha *ha, const char *prefix)
output an HA to the provided fd
Definition: acl.c:1087
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ 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 430 of file acl.c.

References ast_acl::acl, 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, ast_acl::is_invalid, ast_acl::is_realtime, LOG_ERROR, ast_acl::name, NULL, strsep(), and tmp().

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

431 {
432  struct ast_acl *acl = NULL;
433  struct ast_acl *current;
434  struct ast_acl_list *working_list;
435 
436  char *tmp, *list;
437 
438  /* If the ACL list is currently uninitialized, it must be initialized. */
439  if (*path == NULL) {
440  struct ast_acl_list *list;
441  list = ast_calloc(1, sizeof(*list));
442  if (!list) {
443  /* Allocation Error */
444  if (error) {
445  *error = 1;
446  }
447  return;
448  }
449 
450  AST_LIST_HEAD_INIT(list);
451  *path = list;
452  }
453 
454  working_list = *path;
455 
456  AST_LIST_LOCK(working_list);
457 
458  /* First we need to determine if we will need to add a new ACL node or if we can use an existing one. */
459  if (strncasecmp(sense, "a", 1)) {
460  /* The first element in the path should be the unnamed, base ACL. If that's the case, we use it. If not,
461  * we have to make one and link it up appropriately. */
462  current = AST_LIST_FIRST(working_list);
463 
464  if (!current || !ast_strlen_zero(current->name)) {
465  if (acl_new(&acl, "")) {
466  if (error) {
467  *error = 1;
468  }
469  AST_LIST_UNLOCK(working_list);
470  return;
471  }
472  // Need to INSERT the ACL at the head here.
473  AST_LIST_INSERT_HEAD(working_list, acl, list);
474  } else {
475  /* If the first element was already the unnamed base ACL, we just use that one. */
476  acl = current;
477  }
478 
479  /* With the proper ACL set for modification, we can just pass this off to the ast_ha append function. */
480  acl->acl = ast_append_ha(sense, stuff, acl->acl, error);
481 
482  AST_LIST_UNLOCK(working_list);
483  return;
484  }
485 
486  /* We are in ACL append mode, so we know we'll be adding one or more named ACLs. */
487  list = ast_strdupa(stuff);
488 
489  while ((tmp = strsep(&list, ","))) {
490  struct ast_ha *named_ha;
491  int already_included = 0;
492 
493  /* Remove leading whitespace from the string in case the user put spaces between items */
494  tmp = ast_skip_blanks(tmp);
495 
496  /* The first step is to check for a duplicate */
497  AST_LIST_TRAVERSE(working_list, current, list) {
498  if (!strcasecmp(current->name, tmp)) { /* ACL= */
499  /* Inclusion of the same ACL multiple times isn't a catastrophic error, but it will raise the error flag and skip the entry. */
500  ast_log(LOG_ERROR, "Named ACL '%s' occurs multiple times in ACL definition. "
501  "Please update your ACL configuration.\n", tmp);
502  if (error) {
503  *error = 1;
504  }
505  already_included = 1;
506  break;
507  }
508  }
509 
510  if (already_included) {
511  continue;
512  }
513 
514  if (acl_new(&acl, tmp)) {
515  /* This is a catastrophic allocation error and we'll return immediately if this happens. */
516  if (error) {
517  *error = 1;
518  }
519  AST_LIST_UNLOCK(working_list);
520  return;
521  }
522 
523  /* Attempt to grab the Named ACL we are looking for. */
524  named_ha = ast_named_acl_find(tmp, &acl->is_realtime, &acl->is_invalid);
525 
526  /* Set the ACL's ast_ha to the duplicated named ACL retrieved above. */
527  acl->acl = named_ha;
528 
529  /* Raise the named_acl_flag since we are adding a named ACL to the ACL container. */
530  if (named_acl_flag) {
531  *named_acl_flag = 1;
532  }
533 
534  /* Now insert the new ACL at the end of the list. */
535  AST_LIST_INSERT_TAIL(working_list, acl, list);
536  }
537 
538  AST_LIST_UNLOCK(working_list);
539 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int tmp()
Definition: bt_open.c:389
char name[ACL_NAME_LENGTH]
Definition: acl.h:71
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:713
Wrapper for an ast_acl linked list.
Definition: acl.h:76
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
internal representation of ACL entries In principle user applications would have no need for this...
Definition: acl.h:51
int is_realtime
Definition: acl.h:69
#define ast_log
Definition: astobj2.c:42
int is_invalid
Definition: acl.h:70
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_ha * acl
Definition: acl.h:68
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
Definition: test_acl.c:111
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:625
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
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
char * strsep(char **str, const char *delims)
int error(const char *format,...)
Definition: utils/frame.c:999
static int acl_new(struct ast_acl **pointer, const char *name)
Definition: acl.c:305

◆ 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 713 of file acl.c.

References append_ha_core(), and PARSE_PORT_FORBID.

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

714 {
715  return append_ha_core(sense, stuff, path, error, PARSE_PORT_FORBID);
716 }
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:576
enum ast_acl_sense sense
Definition: acl.h:55
int error(const char *format,...)
Definition: utils/frame.c:999

◆ 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 718 of file acl.c.

References append_ha_core().

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

719 {
720  return append_ha_core(sense, stuff, path, error, 0);
721 }
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:576
enum ast_acl_sense sense
Definition: acl.h:55
int error(const char *format,...)
Definition: utils/frame.c:999

◆ 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 800 of file acl.c.

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(), check_peer_ok(), parse_register_contact(), register_verify(), and sip_allow_anyrtp_remote().

800  {
801  return ast_apply_acl_internal(acl_list, addr, purpose ?: "");
802 }
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:758

◆ 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 758 of file acl.c.

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::is_invalid, ast_acl::list, LOG_NOTICE, LOG_WARNING, and ast_acl::name.

Referenced by ast_apply_acl(), and ast_apply_acl_nolog().

759 {
760  struct ast_acl *acl;
761 
762  /* If the list is NULL, there are no rules, so we'll allow automatically. */
763  if (!acl_list) {
764  return AST_SENSE_ALLOW;
765  }
766 
767  AST_LIST_LOCK(acl_list);
768 
769  AST_LIST_TRAVERSE(acl_list, acl, list) {
770  if (acl->is_invalid) {
771  /* In this case, the baseline ACL shouldn't ever trigger this, but if that somehow happens, it'll still be shown. */
772  if (log_prefix) {
773  ast_log(LOG_WARNING, "%sRejecting '%s' due to use of an invalid ACL '%s'.\n",
774  log_prefix, ast_sockaddr_stringify_addr(addr),
775  ast_strlen_zero(acl->name) ? "(BASELINE)" : acl->name);
776  }
777  AST_LIST_UNLOCK(acl_list);
778  return AST_SENSE_DENY;
779  }
780 
781  if (acl->acl) {
782  if (ast_apply_ha(acl->acl, addr) == AST_SENSE_DENY) {
783  if (log_prefix) {
784  ast_log(LOG_NOTICE, "%sRejecting '%s' due to a failure to pass ACL '%s'\n",
785  log_prefix, ast_sockaddr_stringify_addr(addr),
786  ast_strlen_zero(acl->name) ? "(BASELINE)" : acl->name);
787  }
788  AST_LIST_UNLOCK(acl_list);
789  return AST_SENSE_DENY;
790  }
791  }
792  }
793 
794  AST_LIST_UNLOCK(acl_list);
795 
796  return AST_SENSE_ALLOW;
797 }
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:290
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct ast_acl::@218 list
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char name[ACL_NAME_LENGTH]
Definition: acl.h:71
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
int is_invalid
Definition: acl.h:70
struct ast_ha * acl
Definition: acl.h:68
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67
#define LOG_NOTICE
Definition: logger.h:263
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
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:808

◆ 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 804 of file acl.c.

References ast_apply_acl_internal(), and NULL.

Referenced by rtp_address_is_ice_blacklisted(), and stun_address_is_blacklisted().

804  {
805  return ast_apply_acl_internal(acl_list, addr, NULL);
806 }
#define NULL
Definition: resample.c:96
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:758

◆ 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 808 of file acl.c.

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, and ast_ha::sense.

Referenced by ast_apply_acl_internal(), ast_sip_ouraddrfor(), AST_TEST_DEFINE(), ip_identify_match_check(), ip_identify_match_host_lookup(), pjsip_log_test_addr(), and skinny_register().

809 {
810  /* Start optimistic */
811  enum ast_acl_sense res = AST_SENSE_ALLOW;
812  const struct ast_ha *current_ha;
813 
814  for (current_ha = ha; current_ha; current_ha = current_ha->next) {
815  struct ast_sockaddr result;
816  struct ast_sockaddr mapped_addr;
817  const struct ast_sockaddr *addr_to_use;
818  uint16_t save_port;
819 #if 0 /* debugging code */
820  char iabuf[INET_ADDRSTRLEN];
821  char iabuf2[INET_ADDRSTRLEN];
822  /* DEBUG */
823  ast_copy_string(iabuf, ast_sockaddr_stringify(addr), sizeof(iabuf));
824  ast_copy_string(iabuf2, ast_sockaddr_stringify(&current_ha->addr), sizeof(iabuf2));
825  ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2);
826 #endif
827  if (ast_sockaddr_is_ipv4(&current_ha->addr)) {
828  if (ast_sockaddr_is_ipv6(addr)) {
829  if (ast_sockaddr_is_ipv4_mapped(addr)) {
830  /* IPv4 ACLs apply to IPv4-mapped addresses */
831  if (!ast_sockaddr_ipv4_mapped(addr, &mapped_addr)) {
832  ast_log(LOG_ERROR, "%s provided to ast_sockaddr_ipv4_mapped could not be converted. That shouldn't be possible.\n",
833  ast_sockaddr_stringify(addr));
834  continue;
835  }
836  addr_to_use = &mapped_addr;
837  } else {
838  /* An IPv4 ACL does not apply to an IPv6 address */
839  continue;
840  }
841  } else {
842  /* Address is IPv4 and ACL is IPv4. No biggie */
843  addr_to_use = addr;
844  }
845  } else {
847  addr_to_use = addr;
848  } else {
849  /* Address is IPv4 or IPv4 mapped but ACL is IPv6. Skip */
850  continue;
851  }
852  }
853 
854  /* ast_sockaddr_apply_netmask() does not preserve the port, so we need to save and
855  * restore it */
856  save_port = ast_sockaddr_port(addr_to_use);
857 
858  /* For each rule, if this address and the netmask = the net address
859  apply the current rule */
860  if (ast_sockaddr_apply_netmask(addr_to_use, &current_ha->netmask, &result)) {
861  /* Unlikely to happen since we know the address to be IPv4 or IPv6 */
862  continue;
863  }
864 
865  ast_sockaddr_set_port(&result, save_port);
866 
867  if (!ast_sockaddr_cmp_addr(&result, &current_ha->addr)
868  && (!ast_sockaddr_port(&current_ha->addr)
869  || ast_sockaddr_port(&current_ha->addr) == ast_sockaddr_port(&result))) {
870  res = current_ha->sense;
871  }
872  }
873  return res;
874 }
struct ast_ha * next
Definition: acl.h:56
struct ast_sockaddr addr
Definition: acl.h:53
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
enum ast_acl_sense sense
Definition: acl.h:55
Socket address structure.
Definition: netsock2.h:97
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
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
internal representation of ACL entries In principle user applications would have no need for this...
Definition: acl.h:51
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_sockaddr netmask
Definition: acl.h:54
ast_acl_sense
Definition: acl.h:36
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
#define LOG_ERROR
Definition: logger.h:285
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
Determine if this is an IPv4-mapped IPv6 address.
Definition: netsock2.c:507
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static PGresult * result
Definition: cel_pgsql.c:88
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524

◆ 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
Return values
void

Definition at line 255 of file acl.c.

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().

256 {
257  ast_sockaddr_copy(&to->addr, &from->addr);
258  ast_sockaddr_copy(&to->netmask, &from->netmask);
259  to->sense = from->sense;
260 }
struct ast_sockaddr addr
Definition: acl.h:53
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:171
enum ast_acl_sense sense
Definition: acl.h:55
struct ast_sockaddr netmask
Definition: acl.h:54

◆ 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
Return values
Thenew duplicated ast_acl_list

Definition at line 316 of file acl.c.

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 create_addr_from_peer(), and sip_allow_anyrtp_remote().

317 {
318  struct ast_acl_list *clone;
319  struct ast_acl *current_cursor;
320  struct ast_acl *current_clone;
321 
322  /* Early return if we receive a duplication request for a NULL original. */
323  if (!original) {
324  return NULL;
325  }
326 
327  if (!(clone = ast_calloc(1, sizeof(*clone)))) {
328  ast_log(LOG_ERROR, "Failed to allocate ast_acl_list struct while cloning an ACL\n");
329  return NULL;
330  }
331  AST_LIST_HEAD_INIT(clone);
332 
333  AST_LIST_LOCK(original);
334 
335  AST_LIST_TRAVERSE(original, current_cursor, list) {
336  if ((acl_new(&current_clone, current_cursor->name))) {
337  ast_log(LOG_ERROR, "Failed to allocate ast_acl struct while cloning an ACL.\n");
338  ast_free_acl_list(clone);
339  clone = NULL;
340  break;
341  }
342 
343  /* Copy data from original ACL to clone ACL */
344  current_clone->acl = ast_duplicate_ha_list(current_cursor->acl);
345 
346  current_clone->is_invalid = current_cursor->is_invalid;
347  current_clone->is_realtime = current_cursor->is_realtime;
348 
349  AST_LIST_INSERT_TAIL(clone, current_clone, list);
350 
351  if (current_cursor->acl && !current_clone->acl) {
352  /* Deal with failure after adding to clone so we don't have to free
353  * current_clone separately. */
354  ast_log(LOG_ERROR, "Failed to duplicate HA list while cloning ACL.\n");
355  ast_free_acl_list(clone);
356  clone = NULL;
357  break;
358  }
359  }
360 
361  AST_LIST_UNLOCK(original);
362 
363  return clone;
364 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct ast_acl::@218 list
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char name[ACL_NAME_LENGTH]
Definition: acl.h:71
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl_list)
Free a list of ACLs.
Definition: acl.c:233
Wrapper for an ast_acl linked list.
Definition: acl.h:76
#define NULL
Definition: resample.c:96
int is_realtime
Definition: acl.h:69
#define ast_log
Definition: astobj2.c:42
int is_invalid
Definition: acl.h:70
struct ast_ha * acl
Definition: acl.h:68
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:625
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_ha * ast_duplicate_ha_list(struct ast_ha *original)
Duplicate the contents of a list of host access rules.
Definition: acl.c:277
static int acl_new(struct ast_acl **pointer, const char *name)
Definition: acl.c:305

◆ ast_duplicate_ha()

static struct ast_ha* ast_duplicate_ha ( struct ast_ha original)
static

Definition at line 263 of file acl.c.

References ast_calloc, and ast_copy_ha().

Referenced by ast_duplicate_ha_list().

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 }
internal representation of ACL entries In principle user applications would have no need for this...
Definition: acl.h:51
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
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ 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
Return values
Thehead of the list of duplicated ast_has

Definition at line 277 of file acl.c.

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

Referenced by ast_duplicate_acl_list(), and ast_named_acl_find().

278 {
279  struct ast_ha *start = original;
280  struct ast_ha *ret = NULL;
281  struct ast_ha *current, *prev = NULL;
282 
283  while (start) {
284  current = ast_duplicate_ha(start); /* Create copy of this object */
285  if (!current) {
286  ast_free_ha(ret);
287 
288  return NULL;
289  }
290 
291  if (prev) {
292  prev->next = current; /* Link previous to this object */
293  }
294 
295  if (!ret) {
296  ret = current; /* Save starting point */
297  }
298 
299  start = start->next; /* Go to next object */
300  prev = current; /* Save pointer to this object */
301  }
302  return ret; /* Return start of list */
303 }
struct ast_ha * next
Definition: acl.h:56
#define NULL
Definition: resample.c:96
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
internal representation of ACL entries In principle user applications would have no need for this...
Definition: acl.h:51
static struct ast_ha * ast_duplicate_ha(struct ast_ha *original)
Definition: acl.c:263

◆ 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 1052 of file acl.c.

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

Referenced by ast_rtp_prop_set(), and reload_config().

1053 {
1054  char ourhost[MAXHOSTNAMELEN] = "";
1055  struct ast_sockaddr root;
1056  int res, port = ast_sockaddr_port(ourip);
1057 
1058  /* just use the bind address if it is nonzero */
1059  if (!ast_sockaddr_is_any(bindaddr)) {
1060  ast_sockaddr_copy(ourip, bindaddr);
1061  ast_debug(3, "Attached to given IP address\n");
1062  return 0;
1063  }
1064  /* try to use our hostname */
1065  if (gethostname(ourhost, sizeof(ourhost) - 1)) {
1066  ast_log(LOG_WARNING, "Unable to get hostname\n");
1067  } else {
1068  if (resolve_first(ourip, ourhost, PARSE_PORT_FORBID, family) == 0) {
1069  /* reset port since resolve_first wipes this out */
1070  ast_sockaddr_set_port(ourip, port);
1071  return 0;
1072  }
1073  }
1074  ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
1075  /* A.ROOT-SERVERS.NET. */
1076  if (!resolve_first(&root, "A.ROOT-SERVERS.NET", PARSE_PORT_FORBID, 0) &&
1077  !ast_ouraddrfor(&root, ourip)) {
1078  /* reset port since resolve_first wipes this out */
1079  ast_sockaddr_set_port(ourip, port);
1080  return 0;
1081  }
1082  res = get_local_address(ourip);
1083  ast_sockaddr_set_port(ourip, port);
1084  return res;
1085 }
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:171
#define LOG_WARNING
Definition: logger.h:274
static char ourhost[MAXHOSTNAMELEN]
Definition: chan_mgcp.c:238
#define MAXHOSTNAMELEN
Definition: network.h:69
Socket address structure.
Definition: netsock2.h:97
static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag, int family)
Definition: acl.c:876
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
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 ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
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:1005
static int get_local_address(struct ast_sockaddr *ourip)
Definition: acl.c:118

◆ 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.

References ast_acl::acl, ast_free, ast_free_ha(), AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, 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(), reload_config(), rtp_reload(), rtp_unload_acl(), sip_allow_anyrtp_remote(), sip_destroy_peer(), sip_pvt_dtor(), unload_module(), and user_destructor().

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);
244  ast_free(current);
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_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct ast_acl::@218 list
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define NULL
Definition: resample.c:96
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:652
struct ast_ha * acl
Definition: acl.h:68
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define ast_free(a)
Definition: astmm.h:182

◆ 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
Return values
void

Definition at line 222 of file acl.c.

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_gateway(), 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(), reload_config(), test_item_destructor(), transport_localnet_handler(), and unload_module().

223 {
224  struct ast_ha *hal;
225  while (ha) {
226  hal = ha;
227  ha = ha->next;
228  ast_free(hal);
229  }
230 }
struct ast_ha * next
Definition: acl.h:56
internal representation of ACL entries In principle user applications would have no need for this...
Definition: acl.h:51
#define ast_free(a)
Definition: astmm.h:182

◆ 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 1000 of file acl.c.

References ast_get_ip_or_srv(), and NULL.

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

1001 {
1002  return ast_get_ip_or_srv(addr, hostname, NULL);
1003 }
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:897
#define NULL
Definition: resample.c:96
static struct ast_str * hostname
Definition: cdr_mysql.c:77

◆ 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 897 of file acl.c.

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

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

898 {
899  char srv[256];
900  char host[256];
901  int srv_ret = 0;
902  int tportno;
903 
904  if (service) {
905  snprintf(srv, sizeof(srv), "%s.%s", service, hostname);
906  if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, srv)) > 0) {
907  hostname = host;
908  }
909  }
910 
911  if (resolve_first(addr, hostname, PARSE_PORT_FORBID, addr->ss.ss_family) != 0) {
912  return -1;
913  }
914 
915  if (srv_ret > 0) {
916  ast_sockaddr_set_port(addr, tportno);
917  }
918 
919  return 0;
920 }
struct sockaddr_storage ss
Definition: netsock2.h:98
enum ast_cc_service_type service
Definition: chan_sip.c:949
#define NULL
Definition: resample.c:96
static int resolve_first(struct ast_sockaddr *addr, const char *name, int flag, int family)
Definition: acl.c:876
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
static char host[256]
Definition: muted.c:77
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
static struct ast_str * hostname
Definition: cdr_mysql.c:77

◆ 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 723 of file acl.c.

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

Referenced by localnet_to_str(), and match_to_str().

724 {
725  for (; ha; ha = ha->next) {
726  const char *addr;
727 
728  if (ast_sockaddr_port(&ha->addr)) {
729  addr = ast_sockaddr_stringify(&ha->addr);
730  } else {
731  addr = ast_sockaddr_stringify_addr(&ha->addr);
732  }
733 
734  ast_str_append(buf, 0, "%s%s/",
735  ha->sense == AST_SENSE_ALLOW ? "!" : "",
736  addr);
737  /* Separated to avoid duplicating stringified addresses. */
739  if (ha->next) {
740  ast_str_append(buf, 0, ",");
741  }
742  }
743 }
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:290
struct ast_ha * next
Definition: acl.h:56
struct ast_sockaddr addr
Definition: acl.h:53
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:1091
enum ast_acl_sense sense
Definition: acl.h:55
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
struct ast_sockaddr netmask
Definition: acl.h:54
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260

◆ 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 745 of file acl.c.

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

746 {
747  for (; ha; ha = ha->next) {
748  const char *addr = ast_sockaddr_stringify_addr(&ha->addr);
749  ast_str_append(buf, 0, "%s%s/%d",
750  ha->sense == AST_SENSE_ALLOW ? "!" : "",
751  addr, ast_sockaddr_cidr_bits(&ha->netmask));
752  if (ha->next) {
753  ast_str_append(buf, 0, ",");
754  }
755  }
756 }
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:290
struct ast_ha * next
Definition: acl.h:56
struct ast_sockaddr addr
Definition: acl.h:53
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:1091
enum ast_acl_sense sense
Definition: acl.h:55
struct ast_sockaddr netmask
Definition: acl.h:54
int ast_sockaddr_cidr_bits(const struct ast_sockaddr *sa)
Count the 1 bits in a netmask.
Definition: netsock2.c:130

◆ 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 1087 of file acl.c.

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

Referenced by ast_acl_output(), and cli_display_named_acl().

1088 {
1089  char addr[AST_SOCKADDR_BUFLEN];
1090  char *mask;
1091  int index = 0;
1092  for (; ha; ha = ha->next, ++index) {
1093  strcpy(addr, ast_sockaddr_stringify_addr(&ha->addr));
1094  mask = ast_sockaddr_stringify_addr(&ha->netmask);
1095  ast_cli(fd, "%s%3d: %s - %s/%s\n", prefix ?: "", index, ha->sense == AST_SENSE_ALLOW ? "allow" : " deny", addr, mask);
1096  }
1097 }
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:290
struct ast_ha * next
Definition: acl.h:56
#define AST_SOCKADDR_BUFLEN
Definition: netsock2.h:46
struct ast_sockaddr addr
Definition: acl.h:53
enum ast_acl_sense sense
Definition: acl.h:55
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
struct ast_sockaddr netmask
Definition: acl.h:54
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ 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 1005 of file acl.c.

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(), ast_sip_ouraddrfor(), build_gateway(), find_subchannel_and_lock(), sip_acf_channel_read(), and unicast_rtp_request().

1006 {
1007  /*
1008  * We must create the errno string before creating the address
1009  * string because it could wipe out errno on the error return
1010  * paths.
1011  */
1012  const char *sock_err;
1013  int port;
1014  int s;
1015 
1016  /* Preserve our original address port */
1017  port = ast_sockaddr_port(us);
1018 
1019  s = socket(ast_sockaddr_is_ipv6(them) ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
1020  if (s < 0) {
1021  sock_err = ast_strdupa(strerror(errno));
1022  ast_log(LOG_ERROR, "Cannot create socket to %s: %s\n",
1023  ast_sockaddr_stringify_addr(them), sock_err);
1024  return -1;
1025  }
1026 
1027  if (ast_connect(s, them)) {
1028  sock_err = ast_strdupa(strerror(errno));
1029  ast_log(LOG_WARNING, "Cannot connect to %s: %s\n",
1030  ast_sockaddr_stringify_addr(them), sock_err);
1031  close(s);
1032  return -1;
1033  }
1034  if (ast_getsockname(s, us)) {
1035  sock_err = ast_strdupa(strerror(errno));
1036  ast_log(LOG_WARNING, "Cannot get socket name for connection to %s: %s\n",
1037  ast_sockaddr_stringify_addr(them), sock_err);
1038  close(s);
1039  return -1;
1040  }
1041  close(s);
1042 
1043  ast_sockaddr_set_port(us, port);
1044 
1045  ast_debug(3, "For destination '%s', our source address is '%s'.\n",
1048 
1049  return 0;
1050 }
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:290
#define LOG_WARNING
Definition: logger.h:274
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define LOG_ERROR
Definition: logger.h:285
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
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_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
int ast_connect(int sockfd, const struct ast_sockaddr *addr)
Wrapper around connect(2) that uses struct ast_sockaddr.
Definition: netsock2.c:595

◆ 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 953 of file acl.c.

Referenced by config_parse_variables(), reload_config(), and set_config().

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

◆ 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 967 of file acl.c.

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

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

968 {
969  int fval;
970  unsigned int x;
971 
972  if (sscanf(value, "%30i", &fval) == 1) {
973  *tos = fval & 0xFF;
974  return 0;
975  }
976 
977  for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
978  if (!strcasecmp(value, dscp_pool1[x].name)) {
979  *tos = dscp_pool1[x].space << 2;
980  return 0;
981  }
982  }
983 
984  return -1;
985 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const struct dscp_codepoint dscp_pool1[]
Definition: acl.c:929
int value
Definition: syslog.c:37
unsigned int tos
Definition: chan_iax2.c:351
static const char name[]
Definition: cdr_mysql.c:74
unsigned int space
Definition: acl.c:924

◆ 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 987 of file acl.c.

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

Referenced by sip_show_settings().

988 {
989  unsigned int x;
990 
991  for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
992  if (dscp_pool1[x].space == (tos >> 2)) {
993  return dscp_pool1[x].name;
994  }
995  }
996 
997  return "unknown";
998 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const struct dscp_codepoint dscp_pool1[]
Definition: acl.c:929
char * name
Definition: acl.c:923
unsigned int tos
Definition: chan_iax2.c:351

◆ debug_ha_sense_appended()

static void debug_ha_sense_appended ( struct ast_ha ha)
static

Definition at line 566 of file acl.c.

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().

567 {
568  const char *parsed_mask = ast_strdupa(ast_sockaddr_stringify(&ha->netmask));
569 
570  ast_log(LOG_DEBUG, "%s/%s sense %u appended to ACL\n",
572  parsed_mask,
573  ha->sense);
574 }
struct ast_sockaddr addr
Definition: acl.h:53
enum ast_acl_sense sense
Definition: acl.h:55
#define LOG_DEBUG
Definition: logger.h:241
#define ast_log
Definition: astobj2.c:42
struct ast_sockaddr netmask
Definition: acl.h:54
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260

◆ get_local_address()

static int get_local_address ( struct ast_sockaddr ourip)
static

Definition at line 118 of file acl.c.

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

Referenced by ast_find_ourip().

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) {
213  ast_sockaddr_setnull(ourip);
214  ourip->ss.ss_family = AF_INET;
215  ((struct sockaddr_in *)&ourip->ss)->sin_addr = best_addr;
216  }
217  return res;
218 }
struct sockaddr_storage ss
Definition: netsock2.h:98
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define NULL
Definition: resample.c:96
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
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:193
#define ast_free(a)
Definition: astmm.h:182

◆ 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 382 of file acl.c.

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

Referenced by append_ha_core().

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

◆ resolve_first()

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

Definition at line 876 of file acl.c.

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

Referenced by ast_find_ourip(), and ast_get_ip_or_srv().

878 {
879  struct ast_sockaddr *addrs;
880  int addrs_cnt;
881 
882  addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family);
883  if (addrs_cnt > 0) {
884  if (addrs_cnt > 1) {
885  ast_debug(1, "Multiple addresses. Using the first only\n");
886  }
887  ast_sockaddr_copy(addr, &addrs[0]);
888  ast_free(addrs);
889  } else {
890  ast_log(LOG_WARNING, "Unable to lookup '%s'\n", name);
891  return -1;
892  }
893 
894  return 0;
895 }
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:171
#define LOG_WARNING
Definition: logger.h:274
Socket address structure.
Definition: netsock2.h:97
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
long int flag
Definition: f2c.h:83
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
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

◆ 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.

References ast_inet_ntoa().

Referenced by get_local_address().

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 }
char * address
Definition: f2c.h:59
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782

Variable Documentation

◆ dscp_pool1

const struct dscp_codepoint dscp_pool1[]
static

Definition at line 929 of file acl.c.