34 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
36 #include <net/route.h>
40 #include <sys/sockio.h>
42 #elif defined(HAVE_GETIFADDRS)
53 #if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
59 static void score_address(
const struct sockaddr_in *sin,
struct in_addr *best_addr,
int *best_score)
67 if (address[0] ==
'0') {
70 }
else if (strncmp(address,
"127", 3) == 0) {
73 }
else if (strncmp(address,
"10.", 3) == 0) {
76 }
else if (strncmp(address,
"172", 3) == 0) {
78 if (address[4] ==
'1' && address[5] >=
'6' && address[6] ==
'.') {
81 }
else if (address[4] ==
'2' && address[6] ==
'.') {
84 }
else if (address[4] ==
'3' && (address[5] ==
'0' || address[5] ==
'1')) {
91 }
else if (strncmp(address,
"198.1", 5) == 0 && address[5] >=
'8' && address[6] ==
'.') {
94 }
else if (strncmp(address,
"192.168", 7) == 0) {
97 }
else if (strncmp(address,
"169.254", 7) == 0) {
105 }
else if (strncmp(address,
"192.0.2.", 8) == 0) {
112 if (score > *best_score) {
114 memcpy(best_addr, &sin->sin_addr,
sizeof(*best_addr));
118 static int get_local_address(
struct ast_sockaddr *ourip)
122 struct lifreq *ifr = NULL;
125 struct sockaddr_in *sa;
129 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
130 struct ifaddrs *ifap, *ifaphead;
132 const struct sockaddr_in *sin;
134 struct in_addr best_addr;
135 int best_score = -100;
136 memset(&best_addr, 0,
sizeof(best_addr));
138 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
139 rtnerr = getifaddrs(&ifaphead);
146 s = socket(AF_INET, SOCK_STREAM, 0);
149 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) || defined(__GLIBC__)
150 for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
152 if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) {
153 sin = (
const struct sockaddr_in *) ifap->ifa_addr;
157 if (best_score == 0) {
167 ifn.lifn_family = AF_INET;
170 if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
175 bufsz = ifn.lifn_count *
sizeof(
struct lifreq);
180 memset(buf, 0, bufsz);
183 ifc.lifc_len = bufsz;
185 ifc.lifc_family = AF_INET;
187 if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
193 for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) {
194 sa = (
struct sockaddr_in *)&(ifr->lifr_addr);
198 if (best_score == 0) {
208 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
209 freeifaddrs(ifaphead);
212 if (res == 0 && ourip) {
214 ourip->ss.ss_family = AF_INET;
215 ((
struct sockaddr_in *)&ourip->ss)->sin_addr = best_addr;
259 to->sense = from->sense;
263 static struct ast_ha *ast_duplicate_ha(
struct ast_ha *original)
267 if ((new_ha =
ast_calloc(1,
sizeof(*new_ha)))) {
278 struct ast_ha *start = original;
279 struct ast_ha *ret = NULL;
280 struct ast_ha *current, *prev = NULL;
283 current = ast_duplicate_ha(start);
291 prev->next = current;
304 static int acl_new(
struct ast_acl **pointer,
const char *name) {
318 struct ast_acl *current_cursor;
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");
335 if ((acl_new(¤t_clone, current_cursor->
name))) {
336 ast_log(LOG_ERROR,
"Failed to allocate ast_acl struct while cloning an ACL.\n");
350 if (current_cursor->
acl && !current_clone->
acl) {
353 ast_log(LOG_ERROR,
"Failed to duplicate HA list while cloning ACL.\n");
385 if (sscanf(mask_str,
"%30d", &mask) != 1) {
390 struct sockaddr_in sin;
391 if (mask < 0 || mask > 32) {
394 memset(&sin, 0,
sizeof(sin));
395 sin.sin_family = AF_INET;
401 sin.sin_addr.s_addr = htonl(0xFFFFFFFF << (32 - mask));
405 struct sockaddr_in6 sin6;
407 if (mask < 0 || mask > 128) {
410 memset(&sin6, 0,
sizeof(sin6));
411 sin6.sin6_family = AF_INET6;
412 for (i = 0; i < 4; ++i) {
418 V6_WORD(&sin6, i) = htonl(0xFFFFFFFF << (mask < 32 ? (32 - mask) : 0));
419 mask -= mask < 32 ? mask : 32;
422 memcpy(&addr->ss, &sin6,
sizeof(sin6));
423 addr->len =
sizeof(sin6);
453 working_list = *path;
458 if (strncasecmp(sense,
"a", 1)) {
463 if (!current || !ast_strlen_zero(current->
name)) {
464 if (acl_new(&acl,
"")) {
488 while ((tmp = strsep(&list,
","))) {
490 int already_included = 0;
497 if (!strcasecmp(current->
name, tmp)) {
499 ast_log(LOG_ERROR,
"Named ACL '%s' occurs multiple times in ACL definition. "
500 "Please update your ACL configuration.\n", tmp);
504 already_included = 1;
509 if (already_included) {
513 if (acl_new(&acl, tmp)) {
529 if (named_acl_flag) {
565 static void debug_ha_sense_appended(
struct ast_ha *ha)
569 ast_log(LOG_DEBUG,
"%s/%s sense %u appended to ACL\n",
575 static struct ast_ha *append_ha_core(
const char *sense,
const char *stuff,
struct ast_ha *path,
int *error,
int port_flags)
578 struct ast_ha *prev = NULL;
581 char *address = NULL, *mask = NULL;
583 int allowing = strncasecmp(sense,
"p", 1) ? AST_SENSE_DENY : AST_SENSE_ALLOW;
591 while ((tmp = strsep(&list,
","))) {
601 address = strsep(&tmp,
"/");
608 if (*address ==
'!') {
609 ha->sense = (allowing == AST_SENSE_DENY) ? AST_SENSE_ALLOW : AST_SENSE_DENY;
612 ha->sense = allowing;
616 ast_log(LOG_WARNING,
"Invalid IP address: %s\n", address);
625 if ((port_flags & PARSE_PORT_MASK) == PARSE_PORT_FORBID) {
633 ast_log(LOG_NOTICE,
"IPv4-mapped ACL network address specified. "
634 "Converting to an IPv4 ACL network address.\n");
641 }
else if (strchr(mask,
':') || strchr(mask,
'.')) {
645 ast_log(LOG_WARNING,
"Invalid netmask: %s\n", mask);
656 ast_log(LOG_NOTICE,
"IPv4-mapped ACL netmask specified. "
657 "Converting to an IPv4 ACL netmask.\n");
660 if (addr_is_v4 ^ mask_is_v4) {
661 ast_log(LOG_WARNING,
"Address and mask are not using same address scheme.\n");
669 ast_log(LOG_WARNING,
"Invalid CIDR netmask: %s\n", mask);
687 ast_log(LOG_WARNING,
"Unable to apply netmask %s to address %s\n", failmask, failaddr);
704 if (DEBUG_ATLEAST(3)) {
705 debug_ha_sense_appended(ha);
714 return append_ha_core(sense, stuff, path, error, PARSE_PORT_FORBID);
719 return append_ha_core(sense, stuff, path, error, 0);
724 for (; ha; ha = ha->next) {
734 ha->sense == AST_SENSE_ALLOW ?
"!" :
"",
746 for (; ha; ha = ha->next) {
749 ha->sense == AST_SENSE_ALLOW ?
"!" :
"",
757 static enum ast_acl_sense ast_apply_acl_internal(
struct ast_acl_list *acl_list,
const struct ast_sockaddr *addr,
const char *log_prefix)
763 return AST_SENSE_ALLOW;
772 ast_log(LOG_WARNING,
"%sRejecting '%s' due to use of an invalid ACL '%s'.\n",
774 ast_strlen_zero(acl->
name) ?
"(BASELINE)" : acl->
name);
777 return AST_SENSE_DENY;
783 ast_log(LOG_NOTICE,
"%sRejecting '%s' due to a failure to pass ACL '%s'\n",
785 ast_strlen_zero(acl->
name) ?
"(BASELINE)" : acl->
name);
788 return AST_SENSE_DENY;
795 return AST_SENSE_ALLOW;
800 return ast_apply_acl_internal(acl_list, addr, purpose ?:
"");
804 return ast_apply_acl_internal(acl_list, addr, NULL);
810 enum ast_acl_sense res = AST_SENSE_ALLOW;
811 const struct ast_ha *current_ha;
813 for (current_ha = ha; current_ha; current_ha = current_ha->next) {
819 char iabuf[INET_ADDRSTRLEN];
820 char iabuf2[INET_ADDRSTRLEN];
824 ast_debug(1,
"##### Testing %s with %s\n", iabuf, iabuf2);
831 ast_log(LOG_ERROR,
"%s provided to ast_sockaddr_ipv4_mapped could not be converted. That shouldn't be possible.\n",
835 addr_to_use = &mapped_addr;
869 res = current_ha->sense;
875 static int resolve_first(
struct ast_sockaddr *addr,
const char *name,
int flag,
884 ast_debug(1,
"Multiple addresses. Using the first only\n");
889 ast_log(LOG_WARNING,
"Unable to lookup '%s'\n", name);
904 snprintf(srv,
sizeof(srv),
"%s.%s", service, hostname);
905 if ((srv_ret =
ast_get_srv(NULL, host,
sizeof(host), &tportno, srv)) > 0) {
910 if (resolve_first(addr, hostname, PARSE_PORT_FORBID, addr->ss.ss_family) != 0) {
956 if (sscanf(value,
"%30d", &fval) == 1) {
971 if (sscanf(value,
"%30i", &fval) == 1) {
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;
990 for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) {
991 if (dscp_pool1[x].space == (tos >> 2)) {
992 return dscp_pool1[x].name;
1011 const char *sock_err;
1021 ast_log(LOG_ERROR,
"Cannot create socket to %s: %s\n",
1028 ast_log(LOG_WARNING,
"Cannot connect to %s: %s\n",
1035 ast_log(LOG_WARNING,
"Cannot get socket name for connection to %s: %s\n",
1044 ast_debug(3,
"For destination '%s', our source address is '%s'.\n",
1053 char ourhost[MAXHOSTNAMELEN] =
"";
1060 ast_debug(3,
"Attached to given IP address\n");
1064 if (gethostname(ourhost,
sizeof(ourhost) - 1)) {
1065 ast_log(LOG_WARNING,
"Unable to get hostname\n");
1067 if (resolve_first(ourip, ourhost, PARSE_PORT_FORBID, family) == 0) {
1073 ast_debug(3,
"Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n");
1075 if (!resolve_first(&root,
"A.ROOT-SERVERS.NET", PARSE_PORT_FORBID, 0) &&
1081 res = get_local_address(ourip);
1088 char addr[AST_SOCKADDR_BUFLEN];
1091 for (; ha; ha = ha->next, ++index) {
1094 ast_cli(fd,
"%s%3d: %s - %s/%s\n", prefix ?:
"", index, ha->sense == AST_SENSE_ALLOW ?
"allow" :
" deny", addr, mask);
1104 ast_cli(fd,
"%sACL: %s%s\n---------------------------------------------\n",
1105 prefix ?:
"", ast_strlen_zero(acl->
name) ?
"(unnamed)" : acl->
name,
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
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.
void ast_acl_output(int fd, struct ast_acl_list *acl_list, const char *prefix)
output an ACL to the provided fd
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk locking-related definitions:
int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
Get the IP address given a hostname.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
void ast_ha_join(const struct ast_ha *ha, struct ast_str **buf)
Convert HAs to a comma separated string value.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
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.
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
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.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Support for DNS SRV records, used in to locate SIP services.
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.
char name[ACL_NAME_LENGTH]
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.
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl_list)
Free a list of ACLs.
static struct ast_sockaddr address
Address for UDPTL.
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.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
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.
Wrapper for an ast_acl linked list.
static int parse_cidr_mask(struct ast_sockaddr *addr, int is_v4, const char *mask_str)
Parse a netmask in CIDR notation.
Socket address structure.
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
internal representation of ACL entries In principle user applications would have no need for this...
void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
Copy the contents of one HA to another.
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
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.
General Asterisk PBX channel definitions.
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Access Control of various sorts.
int ast_str2cos(const char *value, unsigned int *cos)
Convert a string to the appropriate COS value.
static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
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.
#define ast_malloc(len)
A wrapper for malloc()
#define ast_debug(level,...)
Log a DEBUG message.
an ast_acl is a linked list node of ast_ha structs which may have names.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
const char * ast_tos2str(unsigned int tos)
Convert a TOS value into its string representation.
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.
Wrapper for network related headers, masking differences between various operating systems...
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Support for dynamic strings.
void ast_ha_output(int fd, const struct ast_ha *ha, const char *prefix)
output an HA to the provided fd
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ast_calloc(num, len)
A wrapper for calloc()
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
Find our IP address.
int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
Determine if this is an IPv4-mapped IPv6 address.
int ast_sockaddr_cidr_bits(const struct ast_sockaddr *sa)
Count the 1 bits in a netmask.
struct ast_ha * ast_named_acl_find(const char *name, int *is_realtime, int *is_undefined)
Retrieve a named ACL.
int ast_acl_list_is_empty(struct ast_acl_list *acl_list)
Determines if an ACL is empty or if it contains entries.
struct ast_ha * ast_duplicate_ha_list(struct ast_ha *original)
Duplicate the contents of a list of host access rules.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
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.
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
int ast_getsockname(int sockfd, struct ast_sockaddr *addr)
Wrapper around getsockname(2) that uses struct ast_sockaddr.
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.
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
int ast_connect(int sockfd, const struct ast_sockaddr *addr)
Wrapper around connect(2) that uses struct ast_sockaddr.
#define V6_WORD(sin6, index)
Isolate a 32-bit section of an IPv6 address.
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.