mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 04:11:08 +00:00
Add IPv6 Support To chan_iax2
This patch adds IPv6 support to chan_iax2. Yay! (closes issue ASTERISK-22025) Patches: iax2-ipv6-v5-reviewboard.diff by Michael L. Young (license 5026) Review: https://reviewboard.asterisk.org/r/2660/ ........ Merged revisions 400567 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400568 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
6
CHANGES
6
CHANGES
@@ -770,7 +770,6 @@ Stasis Message Bus
|
|||||||
Stasis can be configured in stasis.conf. Note that these parameters operate
|
Stasis can be configured in stasis.conf. Note that these parameters operate
|
||||||
at a very low level in Asterisk, and generally will not require changes.
|
at a very low level in Asterisk, and generally will not require changes.
|
||||||
|
|
||||||
|
|
||||||
Channel Drivers
|
Channel Drivers
|
||||||
------------------
|
------------------
|
||||||
* When a channel driver is configured to enable jiterbuffers, they are now
|
* When a channel driver is configured to enable jiterbuffers, they are now
|
||||||
@@ -815,6 +814,11 @@ chan_dahdi
|
|||||||
specified to be created, or the keyword 'new' can be used to add channels
|
specified to be created, or the keyword 'new' can be used to add channels
|
||||||
not yet created.
|
not yet created.
|
||||||
|
|
||||||
|
chan_iax2
|
||||||
|
------------------
|
||||||
|
* IPv6 support has been added. We are now able to bind to and
|
||||||
|
communicate using IPv6 addresses.
|
||||||
|
|
||||||
chan_local
|
chan_local
|
||||||
------------------
|
------------------
|
||||||
* The /b option has been removed.
|
* The /b option has been removed.
|
||||||
|
1306
channels/chan_iax2.c
1306
channels/chan_iax2.c
File diff suppressed because it is too large
Load Diff
@@ -47,7 +47,7 @@ struct iax_ies {
|
|||||||
char *challenge;
|
char *challenge;
|
||||||
char *md5_result;
|
char *md5_result;
|
||||||
char *rsa_result;
|
char *rsa_result;
|
||||||
struct sockaddr_in *apparent_addr;
|
struct ast_sockaddr apparent_addr;
|
||||||
unsigned short refresh;
|
unsigned short refresh;
|
||||||
unsigned short dpstatus;
|
unsigned short dpstatus;
|
||||||
unsigned short callno;
|
unsigned short callno;
|
||||||
@@ -153,13 +153,13 @@ struct iax_ie_data {
|
|||||||
void iax_set_output(void (*output)(const char *data));
|
void iax_set_output(void (*output)(const char *data));
|
||||||
/* Choose a different function for errors */
|
/* Choose a different function for errors */
|
||||||
void iax_set_error(void (*output)(const char *data));
|
void iax_set_error(void (*output)(const char *data));
|
||||||
void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen);
|
void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct ast_sockaddr *addr, int datalen);
|
||||||
void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len);
|
void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len);
|
||||||
|
|
||||||
const char *iax_ie2str(int ie);
|
const char *iax_ie2str(int ie);
|
||||||
|
|
||||||
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen);
|
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen);
|
||||||
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct sockaddr_in *sin);
|
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr);
|
||||||
int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value);
|
int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value);
|
||||||
int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value);
|
int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value);
|
||||||
int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value);
|
int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value);
|
||||||
|
@@ -41,6 +41,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
#include "asterisk/config.h"
|
#include "asterisk/config.h"
|
||||||
#include "asterisk/lock.h"
|
#include "asterisk/lock.h"
|
||||||
#include "asterisk/threadstorage.h"
|
#include "asterisk/threadstorage.h"
|
||||||
|
#include "asterisk/netsock2.h"
|
||||||
|
|
||||||
#include "include/iax2.h"
|
#include "include/iax2.h"
|
||||||
#include "include/parser.h"
|
#include "include/parser.h"
|
||||||
@@ -83,13 +84,23 @@ static void (*errorf)(const char *str) = internalerror;
|
|||||||
|
|
||||||
static void dump_addr(char *output, int maxlen, void *value, int len)
|
static void dump_addr(char *output, int maxlen, void *value, int len)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sin;
|
struct ast_sockaddr addr;
|
||||||
if (len == (int)sizeof(sin)) {
|
|
||||||
memcpy(&sin, value, len);
|
if (len == (int)sizeof(struct sockaddr_in)) {
|
||||||
snprintf(output, maxlen, "IPV4 %s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
addr.ss.ss_family = AF_INET;
|
||||||
|
} else if (len == (int) sizeof(struct sockaddr_in6)) {
|
||||||
|
addr.ss.ss_family = AF_INET6;
|
||||||
} else {
|
} else {
|
||||||
ast_copy_string(output, "Invalid Address", maxlen);
|
ast_copy_string(output, "Invalid Address", maxlen);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(&addr, value, len);
|
||||||
|
addr.len = len;
|
||||||
|
|
||||||
|
snprintf(output, maxlen, "%s %s",
|
||||||
|
ast_sockaddr_is_ipv4(&addr) || ast_sockaddr_is_ipv4_mapped(&addr) ? "IPV4" : "IPV6",
|
||||||
|
ast_sockaddr_stringify(&addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_string_hex(char *output, int maxlen, void *value, int len)
|
static void dump_string_hex(char *output, int maxlen, void *value, int len)
|
||||||
@@ -172,12 +183,23 @@ static void dump_datetime(char *output, int maxlen, void *value, int len)
|
|||||||
|
|
||||||
static void dump_ipaddr(char *output, int maxlen, void *value, int len)
|
static void dump_ipaddr(char *output, int maxlen, void *value, int len)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sin;
|
struct ast_sockaddr addr;
|
||||||
if (len == (int)sizeof(unsigned int)) {
|
char *str_addr;
|
||||||
memcpy(&sin.sin_addr, value, len);
|
|
||||||
snprintf(output, maxlen, "%s", ast_inet_ntoa(sin.sin_addr));
|
if (len == (int)sizeof(struct sockaddr_in)) {
|
||||||
} else
|
addr.ss.ss_family = AF_INET;
|
||||||
|
} else if (len == (int)sizeof(struct sockaddr_in6)) {
|
||||||
|
addr.ss.ss_family = AF_INET6;
|
||||||
|
} else {
|
||||||
ast_copy_string(output, "Invalid IPADDR", maxlen);
|
ast_copy_string(output, "Invalid IPADDR", maxlen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&addr, value, len);
|
||||||
|
addr.len = len;
|
||||||
|
|
||||||
|
str_addr = ast_sockaddr_stringify(&addr);
|
||||||
|
ast_copy_string(output, str_addr, maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -564,7 +586,7 @@ void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t
|
|||||||
ast_copy_string(str, cmd, len);
|
ast_copy_string(str, cmd, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
|
void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct ast_sockaddr *addr, int datalen)
|
||||||
{
|
{
|
||||||
const char *framelist[] = {
|
const char *framelist[] = {
|
||||||
"(0?)",
|
"(0?)",
|
||||||
@@ -677,19 +699,22 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
|
|||||||
snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
|
snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
|
||||||
subclass = subclass2;
|
subclass = subclass2;
|
||||||
}
|
}
|
||||||
snprintf(tmp, sizeof(tmp),
|
|
||||||
"%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
|
snprintf(tmp, sizeof(tmp),
|
||||||
|
"%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
|
||||||
dir,
|
dir,
|
||||||
retries, fh->oseqno, fh->iseqno, class, subclass);
|
retries, fh->oseqno, fh->iseqno, class, subclass);
|
||||||
outputf(tmp);
|
outputf(tmp);
|
||||||
snprintf(tmp, sizeof(tmp),
|
snprintf(tmp, sizeof(tmp), " Timestamp: %05lums SCall: %5.5d DCall: %5.5d %s\n",
|
||||||
" Timestamp: %05lums SCall: %5.5d DCall: %5.5d [%s:%d]\n",
|
(unsigned long)ntohl(fh->ts),
|
||||||
(unsigned long)ntohl(fh->ts),
|
ntohs(fh->scallno) & ~IAX_FLAG_FULL,
|
||||||
ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
|
ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
|
||||||
ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
|
ast_sockaddr_stringify(addr));
|
||||||
|
|
||||||
outputf(tmp);
|
outputf(tmp);
|
||||||
if (fh->type == AST_FRAME_IAX)
|
if (fh->type == AST_FRAME_IAX)
|
||||||
dump_ies(fh->iedata, datalen);
|
dump_ies(fh->iedata, datalen);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
|
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
|
||||||
@@ -707,9 +732,9 @@ int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *dat
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct sockaddr_in *sin)
|
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr)
|
||||||
{
|
{
|
||||||
return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
|
return iax_ie_append_raw(ied, ie, addr, addr->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
|
int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
|
||||||
@@ -904,7 +929,8 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
|
|||||||
ies->rsa_result = (char *)data + 2;
|
ies->rsa_result = (char *)data + 2;
|
||||||
break;
|
break;
|
||||||
case IAX_IE_APPARENT_ADDR:
|
case IAX_IE_APPARENT_ADDR:
|
||||||
ies->apparent_addr = ((struct sockaddr_in *)(data + 2));
|
memcpy(&ies->apparent_addr , (struct ast_sockaddr *) (data + 2), len);
|
||||||
|
ies->apparent_addr.len = len;
|
||||||
break;
|
break;
|
||||||
case IAX_IE_REFRESH:
|
case IAX_IE_REFRESH:
|
||||||
if (len != (int)sizeof(unsigned short)) {
|
if (len != (int)sizeof(unsigned short)) {
|
||||||
|
@@ -50,6 +50,18 @@ enum ast_transport {
|
|||||||
AST_TRANSPORT_WSS = 1 << 4,
|
AST_TRANSPORT_WSS = 1 << 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Isolate a 32-bit section of an IPv6 address
|
||||||
|
*
|
||||||
|
* An IPv6 address can be divided into 4 32-bit chunks. This gives
|
||||||
|
* easy access to one of these chunks.
|
||||||
|
*
|
||||||
|
* \param sin6 A pointer to a struct sockaddr_in6
|
||||||
|
* \param index Which 32-bit chunk to operate on. Must be in the range 0-3.
|
||||||
|
*/
|
||||||
|
#define V6_WORD(sin6, index) ((uint32_t *)&((sin6)->sin6_addr))[(index)]
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Socket address structure.
|
* \brief Socket address structure.
|
||||||
*
|
*
|
||||||
@@ -399,6 +411,23 @@ int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags);
|
|||||||
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str,
|
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str,
|
||||||
int flags, int family);
|
int flags, int family);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Apply a netmask to an address and store the result in a separate structure.
|
||||||
|
*
|
||||||
|
* When dealing with IPv6 addresses, one cannot apply a netmask with a simple
|
||||||
|
* logical AND operation. Futhermore, the incoming address may be an IPv4
|
||||||
|
* address and needs to be mapped properly before attempting to apply a rule.
|
||||||
|
*
|
||||||
|
* \param addr The IP address to apply the mask to.
|
||||||
|
* \param netmask The netmask configured in the host access rule.
|
||||||
|
* \param result The resultant address after applying the netmask to the given address
|
||||||
|
* \retval 0 Successfully applied netmask
|
||||||
|
* \retval -1 Failed to apply netmask
|
||||||
|
*/
|
||||||
|
int ast_sockaddr_apply_netmask(const struct ast_sockaddr *addr, const struct ast_sockaddr *netmask,
|
||||||
|
struct ast_sockaddr *result);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \since 1.8
|
* \since 1.8
|
||||||
*
|
*
|
||||||
|
63
main/acl.c
63
main/acl.c
@@ -347,63 +347,6 @@ struct ast_acl_list *ast_duplicate_acl_list(struct ast_acl_list *original)
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief
|
|
||||||
* Isolate a 32-bit section of an IPv6 address
|
|
||||||
*
|
|
||||||
* An IPv6 address can be divided into 4 32-bit chunks. This gives
|
|
||||||
* easy access to one of these chunks.
|
|
||||||
*
|
|
||||||
* \param sin6 A pointer to a struct sockaddr_in6
|
|
||||||
* \param index Which 32-bit chunk to operate on. Must be in the range 0-3.
|
|
||||||
*/
|
|
||||||
#define V6_WORD(sin6, index) ((uint32_t *)&((sin6)->sin6_addr))[(index)]
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief
|
|
||||||
* Apply a netmask to an address and store the result in a separate structure.
|
|
||||||
*
|
|
||||||
* When dealing with IPv6 addresses, one cannot apply a netmask with a simple
|
|
||||||
* logical and operation. Furthermore, the incoming address may be an IPv4 address
|
|
||||||
* and need to be mapped properly before attempting to apply a rule.
|
|
||||||
*
|
|
||||||
* \param addr The IP address to apply the mask to.
|
|
||||||
* \param netmask The netmask configured in the host access rule.
|
|
||||||
* \param result The resultant address after applying the netmask to the given address
|
|
||||||
* \retval 0 Successfully applied netmask
|
|
||||||
* \retval -1 Failed to apply netmask
|
|
||||||
*/
|
|
||||||
static int apply_netmask(const struct ast_sockaddr *addr, const struct ast_sockaddr *netmask,
|
|
||||||
struct ast_sockaddr *result)
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
if (ast_sockaddr_is_ipv4(addr)) {
|
|
||||||
struct sockaddr_in result4 = { 0, };
|
|
||||||
struct sockaddr_in *addr4 = (struct sockaddr_in *) &addr->ss;
|
|
||||||
struct sockaddr_in *mask4 = (struct sockaddr_in *) &netmask->ss;
|
|
||||||
result4.sin_family = AF_INET;
|
|
||||||
result4.sin_addr.s_addr = addr4->sin_addr.s_addr & mask4->sin_addr.s_addr;
|
|
||||||
ast_sockaddr_from_sin(result, &result4);
|
|
||||||
} else if (ast_sockaddr_is_ipv6(addr)) {
|
|
||||||
struct sockaddr_in6 result6 = { 0, };
|
|
||||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &addr->ss;
|
|
||||||
struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *) &netmask->ss;
|
|
||||||
int i;
|
|
||||||
result6.sin6_family = AF_INET6;
|
|
||||||
for (i = 0; i < 4; ++i) {
|
|
||||||
V6_WORD(&result6, i) = V6_WORD(addr6, i) & V6_WORD(mask6, i);
|
|
||||||
}
|
|
||||||
memcpy(&result->ss, &result6, sizeof(result6));
|
|
||||||
result->len = sizeof(result6);
|
|
||||||
} else {
|
|
||||||
/* Unsupported address scheme */
|
|
||||||
res = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief
|
* \brief
|
||||||
* Parse a netmask in CIDR notation
|
* Parse a netmask in CIDR notation
|
||||||
@@ -468,8 +411,6 @@ static int parse_cidr_mask(struct ast_sockaddr *addr, int is_v4, const char *mas
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
|
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
|
||||||
{
|
{
|
||||||
struct ast_acl *acl = NULL;
|
struct ast_acl *acl = NULL;
|
||||||
@@ -693,7 +634,7 @@ struct ast_ha *ast_append_ha(const char *sense, const char *stuff, struct ast_ha
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apply_netmask(&ha->addr, &ha->netmask, &ha->addr)) {
|
if (ast_sockaddr_apply_netmask(&ha->addr, &ha->netmask, &ha->addr)) {
|
||||||
/* This shouldn't happen because ast_sockaddr_parse would
|
/* This shouldn't happen because ast_sockaddr_parse would
|
||||||
* have failed much earlier on an unsupported address scheme
|
* have failed much earlier on an unsupported address scheme
|
||||||
*/
|
*/
|
||||||
@@ -805,7 +746,7 @@ enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockad
|
|||||||
|
|
||||||
/* For each rule, if this address and the netmask = the net address
|
/* For each rule, if this address and the netmask = the net address
|
||||||
apply the current rule */
|
apply the current rule */
|
||||||
if (apply_netmask(addr_to_use, ¤t_ha->netmask, &result)) {
|
if (ast_sockaddr_apply_netmask(addr_to_use, ¤t_ha->netmask, &result)) {
|
||||||
/* Unlikely to happen since we know the address to be IPv4 or IPv6 */
|
/* Unlikely to happen since we know the address to be IPv4 or IPv6 */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -117,7 +117,7 @@ struct ast_netsock *ast_netsock_bindaddr(struct ast_netsock_list *list, struct i
|
|||||||
const int reuseFlag = 1;
|
const int reuseFlag = 1;
|
||||||
|
|
||||||
/* Make a UDP socket */
|
/* Make a UDP socket */
|
||||||
netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
netsocket = socket(ast_sockaddr_is_ipv6(bindaddr) ? AST_AF_INET6 : AST_AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||||
|
|
||||||
if (netsocket < 0) {
|
if (netsocket < 0) {
|
||||||
ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
|
ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
|
||||||
@@ -155,7 +155,7 @@ struct ast_netsock *ast_netsock_bindaddr(struct ast_netsock_list *list, struct i
|
|||||||
ns->ioc = ioc;
|
ns->ioc = ioc;
|
||||||
ns->sockfd = netsocket;
|
ns->sockfd = netsocket;
|
||||||
ns->data = data;
|
ns->data = data;
|
||||||
memcpy(&ns->bindaddr, bindaddr, sizeof(ns->bindaddr));
|
ast_sockaddr_copy(&ns->bindaddr, bindaddr);
|
||||||
ASTOBJ_CONTAINER_LINK(list, ns);
|
ASTOBJ_CONTAINER_LINK(list, ns);
|
||||||
|
|
||||||
return ns;
|
return ns;
|
||||||
@@ -171,10 +171,6 @@ struct ast_netsock *ast_netsock_bind(struct ast_netsock_list *list, struct io_co
|
|||||||
struct ast_sockaddr addr;
|
struct ast_sockaddr addr;
|
||||||
|
|
||||||
if (ast_sockaddr_parse(&addr, bindinfo, 0)) {
|
if (ast_sockaddr_parse(&addr, bindinfo, 0)) {
|
||||||
if (!ast_sockaddr_is_ipv4(&addr)) {
|
|
||||||
ast_log(LOG_WARNING, "Only IPv4 addresses are supported at this time.\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ast_sockaddr_port(&addr)) {
|
if (!ast_sockaddr_port(&addr)) {
|
||||||
ast_sockaddr_set_port(&addr, defaultport);
|
ast_sockaddr_set_port(&addr, defaultport);
|
||||||
|
@@ -297,6 +297,37 @@ cleanup:
|
|||||||
return res_cnt;
|
return res_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ast_sockaddr_apply_netmask(const struct ast_sockaddr *addr, const struct ast_sockaddr *netmask,
|
||||||
|
struct ast_sockaddr *result)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (ast_sockaddr_is_ipv4(addr)) {
|
||||||
|
struct sockaddr_in result4 = { 0, };
|
||||||
|
struct sockaddr_in *addr4 = (struct sockaddr_in *) &addr->ss;
|
||||||
|
struct sockaddr_in *mask4 = (struct sockaddr_in *) &netmask->ss;
|
||||||
|
result4.sin_family = AF_INET;
|
||||||
|
result4.sin_addr.s_addr = addr4->sin_addr.s_addr & mask4->sin_addr.s_addr;
|
||||||
|
ast_sockaddr_from_sin(result, &result4);
|
||||||
|
} else if (ast_sockaddr_is_ipv6(addr)) {
|
||||||
|
struct sockaddr_in6 result6 = { 0, };
|
||||||
|
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &addr->ss;
|
||||||
|
struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *) &netmask->ss;
|
||||||
|
int i;
|
||||||
|
result6.sin6_family = AF_INET6;
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
V6_WORD(&result6, i) = V6_WORD(addr6, i) & V6_WORD(mask6, i);
|
||||||
|
}
|
||||||
|
memcpy(&result->ss, &result6, sizeof(result6));
|
||||||
|
result->len = sizeof(result6);
|
||||||
|
} else {
|
||||||
|
/* Unsupported address scheme */
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
|
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
|
||||||
{
|
{
|
||||||
const struct ast_sockaddr *a_tmp, *b_tmp;
|
const struct ast_sockaddr *a_tmp, *b_tmp;
|
||||||
|
Reference in New Issue
Block a user