mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-19 00:00:09 +00:00
Allow IPv6 addresses for UDPTL streams.
Review: https://reviewboard.asterisk.org/r/795 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@278908 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
172
main/udptl.c
172
main/udptl.c
@@ -82,7 +82,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
static int udptlstart = 4500;
|
||||
static int udptlend = 4599;
|
||||
static int udptldebug; /*!< Are we debugging? */
|
||||
static struct sockaddr_in udptldebugaddr; /*!< Debug packets to/from this host */
|
||||
static struct ast_sockaddr udptldebugaddr; /*!< Debug packets to/from this host */
|
||||
#ifdef SO_NO_CHECK
|
||||
static int nochecksums;
|
||||
#endif
|
||||
@@ -121,8 +121,8 @@ struct ast_udptl {
|
||||
unsigned int lasteventseqn;
|
||||
int nat;
|
||||
int flags;
|
||||
struct sockaddr_in us;
|
||||
struct sockaddr_in them;
|
||||
struct ast_sockaddr us;
|
||||
struct ast_sockaddr them;
|
||||
int *ioid;
|
||||
struct sched_context *sched;
|
||||
struct io_context *io;
|
||||
@@ -172,8 +172,6 @@ struct ast_udptl {
|
||||
|
||||
int verbose;
|
||||
|
||||
struct sockaddr_in far;
|
||||
|
||||
unsigned int tx_seq_no;
|
||||
unsigned int rx_seq_no;
|
||||
unsigned int rx_expected_seq_no;
|
||||
@@ -184,17 +182,20 @@ struct ast_udptl {
|
||||
|
||||
static AST_RWLIST_HEAD_STATIC(protos, ast_udptl_protocol);
|
||||
|
||||
static inline int udptl_debug_test_addr(const struct sockaddr_in *addr)
|
||||
static inline int udptl_debug_test_addr(const struct ast_sockaddr *addr)
|
||||
{
|
||||
if (udptldebug == 0)
|
||||
return 0;
|
||||
if (udptldebugaddr.sin_addr.s_addr) {
|
||||
if (((ntohs(udptldebugaddr.sin_port) != 0) &&
|
||||
(udptldebugaddr.sin_port != addr->sin_port)) ||
|
||||
(udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
|
||||
return 0;
|
||||
|
||||
if (ast_sockaddr_isnull(&udptldebugaddr)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ast_sockaddr_port(&udptldebugaddr)) {
|
||||
return !ast_sockaddr_cmp(&udptldebugaddr, addr);
|
||||
} else {
|
||||
return !ast_sockaddr_cmp_addr(&udptldebugaddr, addr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int decode_length(uint8_t *buf, unsigned int limit, unsigned int *len, unsigned int *pvalue)
|
||||
@@ -672,20 +673,16 @@ static int udptlread(int *id, int fd, short events, void *cbdata)
|
||||
struct ast_frame *ast_udptl_read(struct ast_udptl *udptl)
|
||||
{
|
||||
int res;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t len;
|
||||
struct ast_sockaddr addr;
|
||||
uint16_t seqno = 0;
|
||||
uint16_t *udptlheader;
|
||||
|
||||
len = sizeof(sin);
|
||||
|
||||
/* Cache where the header will go */
|
||||
res = recvfrom(udptl->fd,
|
||||
res = ast_recvfrom(udptl->fd,
|
||||
udptl->rawdata + AST_FRIENDLY_OFFSET,
|
||||
sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
|
||||
0,
|
||||
(struct sockaddr *) &sin,
|
||||
&len);
|
||||
&addr);
|
||||
udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET);
|
||||
if (res < 0) {
|
||||
if (errno != EAGAIN)
|
||||
@@ -696,22 +693,22 @@ struct ast_frame *ast_udptl_read(struct ast_udptl *udptl)
|
||||
}
|
||||
|
||||
/* Ignore if the other side hasn't been given an address yet. */
|
||||
if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port)
|
||||
if (ast_sockaddr_isnull(&udptl->them)) {
|
||||
return &ast_null_frame;
|
||||
}
|
||||
|
||||
if (udptl->nat) {
|
||||
/* Send to whoever sent to us */
|
||||
if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
|
||||
(udptl->them.sin_port != sin.sin_port)) {
|
||||
memcpy(&udptl->them, &sin, sizeof(udptl->them));
|
||||
ast_debug(1, "UDPTL NAT (%s): Using address %s:%d\n",
|
||||
LOG_TAG(udptl), ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
|
||||
if (ast_sockaddr_cmp(&udptl->them, &addr)) {
|
||||
ast_sockaddr_copy(&udptl->them, &addr);
|
||||
ast_debug(1, "UDPTL NAT (%s): Using address %s\n",
|
||||
LOG_TAG(udptl), ast_sockaddr_stringify(&udptl->them));
|
||||
}
|
||||
}
|
||||
|
||||
if (udptl_debug_test_addr(&sin)) {
|
||||
ast_verb(1, "UDPTL (%s): packet from %s:%d (type %d, seq %d, len %d)\n",
|
||||
LOG_TAG(udptl), ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res);
|
||||
if (udptl_debug_test_addr(&addr)) {
|
||||
ast_verb(1, "UDPTL (%s): packet from %s (type %d, seq %d, len %d)\n",
|
||||
LOG_TAG(udptl), ast_sockaddr_stringify(&addr), 0, seqno, res);
|
||||
}
|
||||
if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1)
|
||||
return &ast_null_frame;
|
||||
@@ -916,7 +913,7 @@ unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
|
||||
return udptl->far_max_ifp;
|
||||
}
|
||||
|
||||
struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr)
|
||||
struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *addr)
|
||||
{
|
||||
struct ast_udptl *udptl;
|
||||
int x;
|
||||
@@ -940,10 +937,8 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struc
|
||||
udptl->tx[i].buf_len = -1;
|
||||
}
|
||||
|
||||
udptl->them.sin_family = AF_INET;
|
||||
udptl->us.sin_family = AF_INET;
|
||||
|
||||
if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
if ((udptl->fd = socket(ast_sockaddr_is_ipv6(addr) ?
|
||||
AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
ast_free(udptl);
|
||||
ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
|
||||
return NULL;
|
||||
@@ -961,10 +956,11 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struc
|
||||
}
|
||||
startplace = x;
|
||||
for (;;) {
|
||||
udptl->us.sin_port = htons(x);
|
||||
udptl->us.sin_addr = addr;
|
||||
if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0)
|
||||
ast_sockaddr_copy(&udptl->us, addr);
|
||||
ast_sockaddr_set_port(&udptl->us, x);
|
||||
if (ast_bind(udptl->fd, &udptl->us) == 0) {
|
||||
break;
|
||||
}
|
||||
if (errno != EADDRINUSE) {
|
||||
ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
|
||||
close(udptl->fd);
|
||||
@@ -994,13 +990,6 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struc
|
||||
return udptl;
|
||||
}
|
||||
|
||||
struct ast_udptl *ast_udptl_new(struct sched_context *sched, struct io_context *io, int callbackmode)
|
||||
{
|
||||
struct in_addr ia;
|
||||
memset(&ia, 0, sizeof(ia));
|
||||
return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia);
|
||||
}
|
||||
|
||||
void ast_udptl_set_tag(struct ast_udptl *udptl, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -1021,29 +1010,24 @@ int ast_udptl_setqos(struct ast_udptl *udptl, unsigned int tos, unsigned int cos
|
||||
return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL");
|
||||
}
|
||||
|
||||
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct sockaddr_in *them)
|
||||
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct ast_sockaddr *them)
|
||||
{
|
||||
udptl->them.sin_port = them->sin_port;
|
||||
udptl->them.sin_addr = them->sin_addr;
|
||||
ast_sockaddr_copy(&udptl->them, them);
|
||||
}
|
||||
|
||||
void ast_udptl_get_peer(const struct ast_udptl *udptl, struct sockaddr_in *them)
|
||||
void ast_udptl_get_peer(const struct ast_udptl *udptl, struct ast_sockaddr *them)
|
||||
{
|
||||
memset(them, 0, sizeof(*them));
|
||||
them->sin_family = AF_INET;
|
||||
them->sin_port = udptl->them.sin_port;
|
||||
them->sin_addr = udptl->them.sin_addr;
|
||||
ast_sockaddr_copy(them, &udptl->them);
|
||||
}
|
||||
|
||||
void ast_udptl_get_us(const struct ast_udptl *udptl, struct sockaddr_in *us)
|
||||
void ast_udptl_get_us(const struct ast_udptl *udptl, struct ast_sockaddr *us)
|
||||
{
|
||||
memcpy(us, &udptl->us, sizeof(udptl->us));
|
||||
ast_sockaddr_copy(us, &udptl->us);
|
||||
}
|
||||
|
||||
void ast_udptl_stop(struct ast_udptl *udptl)
|
||||
{
|
||||
memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr));
|
||||
memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port));
|
||||
ast_sockaddr_setnull(&udptl->them);
|
||||
}
|
||||
|
||||
void ast_udptl_destroy(struct ast_udptl *udptl)
|
||||
@@ -1068,9 +1052,10 @@ int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
/* If we have no peer, return immediately */
|
||||
if (s->them.sin_addr.s_addr == INADDR_ANY)
|
||||
/* If we have no peer, return immediately */
|
||||
if (ast_sockaddr_isnull(&s->them)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If there is no data length, return immediately */
|
||||
if (f->datalen == 0)
|
||||
@@ -1097,13 +1082,13 @@ int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
|
||||
/* Cook up the UDPTL packet, with the relevant EC info. */
|
||||
len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, len);
|
||||
|
||||
if ((signed int) len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) {
|
||||
if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0)
|
||||
ast_log(LOG_NOTICE, "(%s): UDPTL Transmission error to %s:%d: %s\n",
|
||||
LOG_TAG(s), ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), strerror(errno));
|
||||
if ((signed int) len > 0 && !ast_sockaddr_isnull(&s->them)) {
|
||||
if ((res = ast_sendto(s->fd, buf, len, 0, &s->them)) < 0)
|
||||
ast_log(LOG_NOTICE, "(%s): UDPTL Transmission error to %s: %s\n",
|
||||
LOG_TAG(s), ast_sockaddr_stringify(&s->them), strerror(errno));
|
||||
if (udptl_debug_test_addr(&s->them))
|
||||
ast_verb(1, "UDPTL (%s): packet to %s:%d (type %d, seq %d, len %d)\n",
|
||||
LOG_TAG(s), ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), 0, seq, len);
|
||||
ast_verb(1, "UDPTL (%s): packet to %s (type %d, seq %d, len %d)\n",
|
||||
LOG_TAG(s), ast_sockaddr_stringify(&s->them), 0, seq, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1156,10 +1141,10 @@ int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
|
||||
struct ast_udptl *p1;
|
||||
struct ast_udptl_protocol *pr0;
|
||||
struct ast_udptl_protocol *pr1;
|
||||
struct sockaddr_in ac0;
|
||||
struct sockaddr_in ac1;
|
||||
struct sockaddr_in t0;
|
||||
struct sockaddr_in t1;
|
||||
struct ast_sockaddr ac0;
|
||||
struct ast_sockaddr ac1;
|
||||
struct ast_sockaddr t0;
|
||||
struct ast_sockaddr t1;
|
||||
void *pvt0;
|
||||
void *pvt1;
|
||||
int to;
|
||||
@@ -1224,19 +1209,19 @@ int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
|
||||
to = -1;
|
||||
ast_udptl_get_peer(p1, &t1);
|
||||
ast_udptl_get_peer(p0, &t0);
|
||||
if (inaddrcmp(&t1, &ac1)) {
|
||||
ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n",
|
||||
c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port));
|
||||
ast_debug(1, "Oooh, '%s' was %s:%d\n",
|
||||
c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port));
|
||||
memcpy(&ac1, &t1, sizeof(ac1));
|
||||
if (ast_sockaddr_cmp(&t1, &ac1)) {
|
||||
ast_debug(1, "Oooh, '%s' changed end address to %s\n",
|
||||
c1->name, ast_sockaddr_stringify(&t1));
|
||||
ast_debug(1, "Oooh, '%s' was %s\n",
|
||||
c1->name, ast_sockaddr_stringify(&ac1));
|
||||
ast_sockaddr_copy(&ac1, &t1);
|
||||
}
|
||||
if (inaddrcmp(&t0, &ac0)) {
|
||||
ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n",
|
||||
c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port));
|
||||
ast_debug(1, "Oooh, '%s' was %s:%d\n",
|
||||
c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port));
|
||||
memcpy(&ac0, &t0, sizeof(ac0));
|
||||
if (ast_sockaddr_cmp(&t0, &ac0)) {
|
||||
ast_debug(1, "Oooh, '%s' changed end address to %s\n",
|
||||
c0->name, ast_sockaddr_stringify(&t0));
|
||||
ast_debug(1, "Oooh, '%s' was %s\n",
|
||||
c0->name, ast_sockaddr_stringify(&ac0));
|
||||
ast_sockaddr_copy(&ac0, &t0);
|
||||
}
|
||||
who = ast_waitfor_n(cs, 2, &to);
|
||||
if (!who) {
|
||||
@@ -1274,12 +1259,6 @@ int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
|
||||
|
||||
static char *handle_cli_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct ast_hostent ahp;
|
||||
int port;
|
||||
char *p;
|
||||
char *arg;
|
||||
|
||||
switch (cmd) {
|
||||
case CLI_INIT:
|
||||
e->command = "udptl set debug {on|off|ip}";
|
||||
@@ -1308,27 +1287,16 @@ static char *handle_cli_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct
|
||||
return CLI_SHOWUSAGE;
|
||||
}
|
||||
} else {
|
||||
struct ast_sockaddr *addrs;
|
||||
if (strncasecmp(a->argv[3], "ip", 2))
|
||||
return CLI_SHOWUSAGE;
|
||||
port = 0;
|
||||
arg = ast_strdupa(a->argv[4]);
|
||||
p = strstr(arg, ":");
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
p++;
|
||||
port = atoi(p);
|
||||
}
|
||||
hp = ast_gethostbyname(arg, &ahp);
|
||||
if (hp == NULL)
|
||||
if (!ast_sockaddr_resolve(&addrs, a->argv[4], 0, 0)) {
|
||||
return CLI_SHOWUSAGE;
|
||||
udptldebugaddr.sin_family = AF_INET;
|
||||
memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
|
||||
udptldebugaddr.sin_port = htons(port);
|
||||
if (port == 0)
|
||||
ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
|
||||
else
|
||||
ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
|
||||
}
|
||||
ast_sockaddr_copy(&udptldebugaddr, &addrs[0]);
|
||||
ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_sockaddr_stringify(&udptldebugaddr));
|
||||
udptldebug = 1;
|
||||
ast_free(addrs);
|
||||
}
|
||||
|
||||
return CLI_SUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user