Allow IPv6 addresses for UDPTL streams.
authorMark Michelson <mmichelson@digium.com>
Fri, 23 Jul 2010 15:16:33 +0000 (15:16 +0000)
committerMark Michelson <mmichelson@digium.com>
Fri, 23 Jul 2010 15:16:33 +0000 (15:16 +0000)
Review: https://reviewboard.asterisk.org/r/795

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@278908 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
channels/sip/include/sip.h
include/asterisk/udptl.h
main/udptl.c

index 0bb691c..d7edb83 100644 (file)
@@ -4783,11 +4783,8 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
        dialog->capability = peer->capability;
        dialog->prefs = peer->prefs;
        if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
-               struct sockaddr_in bindaddr_tmp;
-
                /* t38pt_udptl was enabled in the peer and not in [general] */
-               ast_sockaddr_to_sin(&bindaddr, &bindaddr_tmp);
-               if (dialog->udptl || (!dialog->udptl && (dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr_tmp.sin_addr)))) {
+               if (dialog->udptl || (!dialog->udptl && (dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &bindaddr)))) {
                        dialog->t38_maxdatagram = peer->t38_maxdatagram;
                        set_t38_capabilities(dialog);
                } else {
@@ -7061,10 +7058,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
 
        if (sip_methods[intended_method].need_rtp) {
                if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) {
-                       struct sockaddr_in bindaddr_tmp;
-
-                       ast_sockaddr_to_sin(&bindaddr, &bindaddr_tmp);
-                       if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr_tmp.sin_addr))) {
+                       if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &bindaddr))) {
                                ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
                                p->t38_maxdatagram = global_t38_maxdatagram;
                        } else {
@@ -7798,7 +7792,6 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
        int vportno = -1;               /*!< RTP Video port number */
        int tportno = -1;               /*!< RTP Text port number */
        int udptlportno = -1;           /*!< UDPTL Image port number */
-       struct sockaddr_in isin;        /*!< image socket address */
 
        /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */     
        format_t peercapability = 0, vpeercapability = 0, tpeercapability = 0;
@@ -8266,27 +8259,18 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
        /* Setup image address and port */
        if (p->udptl) {
                if (udptlportno > 0) {
-                       ast_sockaddr_set_port(isa, udptlportno);
                        if (ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {
-                               struct sockaddr_in remote_address = { 0, };
-                               struct ast_sockaddr remote_address_tmp;
-
-                               ast_rtp_instance_get_remote_address(p->rtp,
-                                                                   &remote_address_tmp);
-                               ast_sockaddr_to_sin(&remote_address_tmp,
-                                                   &remote_address);
-                               if (remote_address.sin_addr.s_addr) {
-                                       memcpy(&isin, &remote_address, sizeof(isin));
+                               ast_rtp_instance_get_remote_address(p->rtp, isa);
+                               if (!ast_sockaddr_isnull(isa)) {
                                        if (debug) {
-                                               ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_inet_ntoa(isin.sin_addr));
+                                               ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_sockaddr_stringify(isa));
                                        }
                                }
-                       } else {
-                               ast_sockaddr_to_sin(isa, &isin);
                        }
-                       ast_udptl_set_peer(p->udptl, &isin);
+                       ast_sockaddr_set_port(isa, udptlportno);
+                       ast_udptl_set_peer(p->udptl, isa);
                        if (debug)
-                               ast_debug(1,"Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(isin.sin_addr), ntohs(isin.sin_port));
+                               ast_debug(1,"Peer T.38 UDPTL is at port %s\n", ast_sockaddr_stringify(isa));
 
                        /* verify the far max ifp can be calculated. this requires far max datagram to be set. */
                        if (!ast_udptl_get_far_max_datagram(p->udptl)) {
@@ -10166,12 +10150,11 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
        struct ast_sockaddr addr = { {0,} };
        struct ast_sockaddr vaddr = { {0,} };
        struct ast_sockaddr taddr = { {0,} };
+       struct ast_sockaddr udptladdr = { {0,} };
        struct ast_sockaddr dest = { {0,} };
        struct ast_sockaddr vdest = { {0,} };
        struct ast_sockaddr tdest = { {0,} };
-       struct sockaddr_in dest_tmp;
-       struct sockaddr_in udptlsin = { 0, };
-       struct sockaddr_in udptldest = { 0, };
+       struct ast_sockaddr udptldest = { {0,} };
 
        /* SDP fields */
        char *version =         "v=0\r\n";              /* Protocol version */
@@ -10406,29 +10389,29 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
 
        if (add_t38) {
                /* Our T.38 end is */
-               ast_udptl_get_us(p->udptl, &udptlsin);
+               ast_udptl_get_us(p->udptl, &udptladdr);
 
                /* Determine T.38 UDPTL destination */
-               if (p->udptlredirip.sin_addr.s_addr) {
-                       udptldest.sin_port = p->udptlredirip.sin_port;
-                       udptldest.sin_addr = p->udptlredirip.sin_addr;
+               if (!ast_sockaddr_isnull(&p->udptlredirip)) {
+                       ast_sockaddr_copy(&udptldest, &p->udptlredirip);
                } else {
-                       ast_sockaddr_to_sin(&p->ourip, &udptldest);
-                       udptldest.sin_port = udptlsin.sin_port;
+                       ast_sockaddr_copy(&udptldest, &p->ourip);
+                       ast_sockaddr_set_port(&udptldest, ast_sockaddr_port(&udptladdr));
                }
 
                if (debug) {
-                       ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_sockaddr_stringify_addr(&p->ourip), ntohs(udptlsin.sin_port));
+                       ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_sockaddr_stringify_addr(&p->ourip), ast_sockaddr_port(&udptladdr));
                }
 
                /* We break with the "recommendation" and send our IP, in order that our
                   peer doesn't have to ast_gethostbyname() us */
 
-               ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port));
+               ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ast_sockaddr_port(&udptldest));
 
-               ast_sockaddr_to_sin(&dest, &dest_tmp);
-               if (udptldest.sin_addr.s_addr != dest_tmp.sin_addr.s_addr) {
-                       ast_str_append(&m_modem, 0, "c=IN IP4 %s\r\n", ast_inet_ntoa(udptldest.sin_addr));
+               if (!ast_sockaddr_cmp(&udptldest, &dest)) {
+                       ast_str_append(&m_modem, 0, "c=IN %s %s\r\n",
+                                       (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ?
+                                       "IP6" : "IP4", ast_sockaddr_stringify_addr(&udptldest));
                }
 
                ast_str_append(&a_modem, 0, "a=T38FaxVersion:%d\r\n", p->t38.our_parms.version);
@@ -21127,10 +21110,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                }
                /* If T38 is needed but not present, then make it magically appear */
                if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && !p->udptl) {
-                       struct sockaddr_in bindaddr_sin_tmp;
-
-                       ast_sockaddr_to_sin(&bindaddr, &bindaddr_sin_tmp);
-                       if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr_sin_tmp.sin_addr))) {
+                       if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &bindaddr))) {
                                p->t38_maxdatagram = global_t38_maxdatagram;
                                set_t38_capabilities(p);
                        } else {
@@ -27247,14 +27227,13 @@ static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl)
                memset(&p->udptlredirip, 0, sizeof(p->udptlredirip));
        }
        if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
-               struct sockaddr_in ourip_sin;
-               ast_sockaddr_to_sin(&p->ourip, &ourip_sin);
                if (!p->pendinginvite) {
-                       ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : ourip_sin.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
-
+                       ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s\n",
+                                       p->callid, ast_sockaddr_stringify(udptl ? &p->udptlredirip : &p->ourip));
                        transmit_reinvite_with_sdp(p, TRUE, FALSE);
                } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
-                       ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : ourip_sin.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
+                       ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s\n",
+                                       p->callid, ast_sockaddr_stringify(udptl ? &p->udptlredirip : &p->ourip));
                        ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
                }
        }
index b4137bf..6da0c44 100644 (file)
@@ -1001,7 +1001,7 @@ struct sip_pvt {
        int authtries;                        /*!< Times we've tried to authenticate */
        struct sip_proxy *outboundproxy;      /*!< Outbound proxy for this dialog. Use ref_proxy to set this instead of setting it directly*/
        struct t38properties t38;             /*!< T38 settings */
-       struct sockaddr_in udptlredirip;      /*!< Where our T.38 UDPTL should be going if not to us */
+       struct ast_sockaddr udptlredirip;     /*!< Where our T.38 UDPTL should be going if not to us */
        struct ast_udptl *udptl;              /*!< T.38 UDPTL session */
        int callingpres;                      /*!< Calling presentation */
        int expiry;                         /*!< How long we take to expire */
index 3cbfeeb..af80681 100644 (file)
@@ -31,6 +31,7 @@
 #include "asterisk/io.h"
 #include "asterisk/sched.h"
 #include "asterisk/channel.h"
+#include "asterisk/netsock2.h"
 
 
 enum ast_t38_ec_modes {
@@ -56,9 +57,7 @@ struct ast_udptl;
 
 typedef int (*ast_udptl_callback)(struct ast_udptl *udptl, struct ast_frame *f, void *data);
 
-struct ast_udptl *ast_udptl_new(struct sched_context *sched, struct io_context *io, int callbackmode);
-
-struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr in);
+struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *in);
 
 /*!
  * \brief Associates a character string 'tag' with a UDPTL session.
@@ -75,11 +74,11 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struc
  */
 void __attribute__((format(printf, 2, 3))) ast_udptl_set_tag(struct ast_udptl *udptl, const char *format, ...);
 
-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);
 
-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);
 
-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);
 
 void ast_udptl_destroy(struct ast_udptl *udptl);
 
index 113a183..1000449 100644 (file)
@@ -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;