Merged revisions 89536 via svnmerge from
[asterisk/asterisk.git] / main / udptl.c
index 9e8fdf1..8ae65b9 100644 (file)
@@ -8,43 +8,62 @@
  *
  * Steve Underwood <steveu@coppice.org>
  *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
  * This program is free software, distributed under the terms of
- * the GNU General Public License
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
  *
  * A license has been granted to Digium (via disclaimer) for the use of
  * this code.
  */
 
+/*! 
+ * \file 
+ *
+ * \brief UDPTL support for T.38 faxing
+ * 
+ *
+ * \author Mark Spencer <markster@digium.com>,  Steve Underwood <steveu@coppice.org>
+ * 
+ * \page T38fax_udptl T38 fax passhtrough :: UDPTL
+ *
+ * Asterisk supports T.38 fax passthrough. Asterisk will not be a client, server
+ * or any form of gateway. Currently fax passthrough is only implemented in the
+ * SIP channel for strict SIP to SIP calls. If you are using chan_local or chan_agent
+ * as a proxy channel, T.38 passthrough will not work.
+ *
+ * UDPTL is handled very much like RTP. It can be reinvited to go directly between
+ * the endpoints, without involving Asterisk in the media stream.
+ * 
+ * \b References:
+ * - chan_sip.c
+ * - udptl.c
+ */
+
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <sys/time.h>
 #include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
 #include <fcntl.h>
 
 #include "asterisk/udptl.h"
 #include "asterisk/frame.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
 #include "asterisk/channel.h"
 #include "asterisk/acl.h"
-#include "asterisk/channel.h"
 #include "asterisk/config.h"
 #include "asterisk/lock.h"
 #include "asterisk/utils.h"
+#include "asterisk/netsock.h"
 #include "asterisk/cli.h"
 #include "asterisk/unaligned.h"
-#include "asterisk/utils.h"
 
 #define UDPTL_MTU              1200
 
@@ -55,17 +74,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define TRUE (!FALSE)
 #endif
 
-static int udptlstart = 0;
-static int udptlend = 0;
-static int udptldebug = 0;                  /* Are we debugging? */
-static struct sockaddr_in udptldebugaddr;   /* Debug packets to/from this host */
+static int udptlstart;
+static int udptlend;
+static int udptldebug;                     /*!< Are we debugging? */
+static struct sockaddr_in udptldebugaddr;   /*!< Debug packets to/from this host */
 #ifdef SO_NO_CHECK
-static int nochecksums = 0;
+static int nochecksums;
 #endif
-static int udptlfectype = 0;
-static int udptlfecentries = 0;
-static int udptlfecspan = 0;
-static int udptlmaxdatagram = 0;
+static int udptlfectype;
+static int udptlfecentries;
+static int udptlfecspan;
+static int udptlmaxdatagram;
 
 #define LOCAL_FAX_MAX_DATAGRAM      400
 #define MAX_FEC_ENTRIES             5
@@ -87,6 +106,7 @@ typedef struct {
        int fec_entries;
 } udptl_fec_rx_buffer_t;
 
+/*! \brief Structure for an UDPTL session */
 struct ast_udptl {
        int fd;
        char resp;
@@ -137,7 +157,7 @@ struct ast_udptl {
        udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
 };
 
-static struct ast_udptl_protocol *protos = NULL;
+static AST_RWLIST_HEAD_STATIC(protos, ast_udptl_protocol);
 
 static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len);
 static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len);
@@ -296,8 +316,7 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
 
        ptr = 0;
        ifp_no = 0;
-       s->f[0].prev = NULL;
-       s->f[0].next = NULL;
+       memset(&s->f[0], 0, sizeof(s->f[0]));
 
        /* Decode seq_number */
        if (ptr + 2 > len)
@@ -342,11 +361,9 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
                                        s->f[ifp_no].data = (uint8_t *) bufs[i - 1];
                                        s->f[ifp_no].offset = 0;
                                        s->f[ifp_no].src = "UDPTL";
-                                       if (ifp_no > 0) {
-                                               s->f[ifp_no].prev = &s->f[ifp_no - 1];
-                                               s->f[ifp_no - 1].next = &s->f[ifp_no];
-                                       }
-                                       s->f[ifp_no].next = NULL;
+                                       if (ifp_no > 0)
+                                               AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
+                                       AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
                                        ifp_no++;
                                }
                        }
@@ -364,11 +381,9 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
                        s->f[ifp_no].data = (uint8_t *) ifp;
                        s->f[ifp_no].offset = 0;
                        s->f[ifp_no].src = "UDPTL";
-                       if (ifp_no > 0) {
-                               s->f[ifp_no].prev = &s->f[ifp_no - 1];
-                               s->f[ifp_no - 1].next = &s->f[ifp_no];
-                       }
-                       s->f[ifp_no].next = NULL;
+                       if (ifp_no > 0)
+                               AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
+                       AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
                }
        }
        else
@@ -465,11 +480,9 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
                                s->f[ifp_no].data = s->rx[l].buf;
                                s->f[ifp_no].offset = 0;
                                s->f[ifp_no].src = "UDPTL";
-                               if (ifp_no > 0) {
-                                       s->f[ifp_no].prev = &s->f[ifp_no - 1];
-                                       s->f[ifp_no - 1].next = &s->f[ifp_no];
-                               }
-                               s->f[ifp_no].next = NULL;
+                               if (ifp_no > 0)
+                                       AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
+                               AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
                                ifp_no++;
                        }
                }
@@ -483,11 +496,9 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
                s->f[ifp_no].data = (uint8_t *) ifp;
                s->f[ifp_no].offset = 0;
                s->f[ifp_no].src = "UDPTL";
-               if (ifp_no > 0) {
-                       s->f[ifp_no].prev = &s->f[ifp_no - 1];
-                       s->f[ifp_no - 1].next = &s->f[ifp_no];
-               }
-               s->f[ifp_no].next = NULL;
+               if (ifp_no > 0)
+                       AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
+               AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
        }
 
        s->rx_seq_no = seq_no + 1;
@@ -673,13 +684,13 @@ struct ast_frame *ast_udptl_read(struct ast_udptl *udptl)
                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_log(LOG_DEBUG, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
+                       ast_debug(1, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
                }
        }
 
        if (udptl_debug_test_addr(&sin)) {
-               ast_verbose("Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n",
-                       ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res);
+               ast_verb(1, "Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n",
+                               ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res);
        }
 #if 0
        printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res);
@@ -721,7 +732,7 @@ void ast_udptl_set_error_correction_scheme(struct ast_udptl* udptl, int ec)
                        udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE;
                        break;
                default:
-                       ast_log(LOG_WARNING, "error correction parameter invalid");
+                       ast_log(LOG_WARNING, "error correction parameter invalid\n");
                };
        } else
                ast_log(LOG_WARNING, "udptl structure is null\n");
@@ -798,7 +809,7 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struc
        udptl->us.sin_family = AF_INET;
 
        if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               free(udptl);
+               ast_free(udptl);
                ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
                return NULL;
        }
@@ -819,7 +830,7 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struc
                if (errno != EADDRINUSE) {
                        ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
                        close(udptl->fd);
-                       free(udptl);
+                       ast_free(udptl);
                        return NULL;
                }
                if (++x > udptlend)
@@ -827,7 +838,7 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struc
                if (x == startplace) {
                        ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
                        close(udptl->fd);
-                       free(udptl);
+                       ast_free(udptl);
                        return NULL;
                }
        }
@@ -847,13 +858,9 @@ struct ast_udptl *ast_udptl_new(struct sched_context *sched, struct io_context *
        return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia);
 }
 
-int ast_udptl_settos(struct ast_udptl *udptl, int tos)
+int ast_udptl_setqos(struct ast_udptl *udptl, int tos, int cos)
 {
-       int res;
-
-       if ((res = setsockopt(udptl->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
-               ast_log(LOG_WARNING, "UDPTL unable to set TOS to %d\n", tos);
-       return res;
+       return ast_netsock_set_qos(udptl->fd, tos, cos);
 }
 
 void ast_udptl_set_peer(struct ast_udptl *udptl, struct sockaddr_in *them)
@@ -886,7 +893,7 @@ void ast_udptl_destroy(struct ast_udptl *udptl)
                ast_io_remove(udptl->io, udptl->ioid);
        if (udptl->fd > -1)
                close(udptl->fd);
-       free(udptl);
+       ast_free(udptl);
 }
 
 int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
@@ -928,52 +935,40 @@ int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
 
 void ast_udptl_proto_unregister(struct ast_udptl_protocol *proto)
 {
-       struct ast_udptl_protocol *cur;
-       struct ast_udptl_protocol *prev;
-
-       cur = protos;
-       prev = NULL;
-       while (cur) {
-               if (cur == proto) {
-                       if (prev)
-                               prev->next = proto->next;
-                       else
-                               protos = proto->next;
-                       return;
-               }
-               prev = cur;
-               cur = cur->next;
-       }
+       AST_RWLIST_WRLOCK(&protos);
+       AST_RWLIST_REMOVE(&protos, proto, list);
+       AST_RWLIST_UNLOCK(&protos);
 }
 
 int ast_udptl_proto_register(struct ast_udptl_protocol *proto)
 {
        struct ast_udptl_protocol *cur;
 
-       cur = protos;
-       while (cur) {
+       AST_RWLIST_WRLOCK(&protos);
+       AST_RWLIST_TRAVERSE(&protos, cur, list) {
                if (cur->type == proto->type) {
                        ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
+                       AST_RWLIST_UNLOCK(&protos);
                        return -1;
                }
-               cur = cur->next;
        }
-       proto->next = protos;
-       protos = proto;
+       AST_RWLIST_INSERT_TAIL(&protos, proto, list);
+       AST_RWLIST_UNLOCK(&protos);
        return 0;
 }
 
 static struct ast_udptl_protocol *get_proto(struct ast_channel *chan)
 {
-       struct ast_udptl_protocol *cur;
+       struct ast_udptl_protocol *cur = NULL;
 
-       cur = protos;
-       while (cur) {
+       AST_RWLIST_RDLOCK(&protos);
+       AST_RWLIST_TRAVERSE(&protos, cur, list) {
                if (cur->type == chan->tech->type)
-                       return cur;
-               cur = cur->next;
+                       break;
        }
-       return NULL;
+       AST_RWLIST_UNLOCK(&protos);
+
+       return cur;
 }
 
 int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
@@ -1044,7 +1039,7 @@ int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
                if ((c0->tech_pvt != pvt0) ||
                        (c1->tech_pvt != pvt1) ||
                        (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
-                               ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
+                               ast_debug(1, "Oooh, something is weird, backing out\n");
                                /* Tell it to try again later */
                                return -3;
                }
@@ -1052,22 +1047,22 @@ int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
                ast_udptl_get_peer(p1, &t1);
                ast_udptl_get_peer(p0, &t0);
                if (inaddrcmp(&t1, &ac1)) {
-                       ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 
+                       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_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 
+                       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 (inaddrcmp(&t0, &ac0)) {
-                       ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 
+                       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_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 
+                       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));
                }
                who = ast_waitfor_n(cs, 2, &to);
                if (!who) {
-                       ast_log(LOG_DEBUG, "Ooh, empty read...\n");
+                       ast_debug(1, "Ooh, empty read...\n");
                        /* check for hangup / whentohangup */
                        if (ast_check_hangup(c0) || ast_check_hangup(c1))
                                break;
@@ -1077,7 +1072,7 @@ int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
                if (!f) {
                        *fo = f;
                        *rc = who;
-                       ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
+                       ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup");
                        /* That's all we needed */
                        return 0;
                } else {
@@ -1099,7 +1094,7 @@ int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
        return -1;
 }
 
-static int udptl_do_debug_ip(int fd, int argc, char *argv[])
+static char *handle_cli_udptl_debug_ip(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        struct hostent *hp;
        struct ast_hostent ahp;
@@ -1107,10 +1102,22 @@ static int udptl_do_debug_ip(int fd, int argc, char *argv[])
        char *p;
        char *arg;
 
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "udptl debug ip";
+               e->usage =
+                       "Usage: udptl debug [ip host[:port]]\n"
+                       "       Enable dumping of all UDPTL packets to and from host.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
        port = 0;
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-       arg = argv[3];
+
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
+       arg = a->argv[3];
        p = strstr(arg, ":");
        if (p) {
                *p = '\0';
@@ -1119,61 +1126,77 @@ static int udptl_do_debug_ip(int fd, int argc, char *argv[])
        }
        hp = ast_gethostbyname(arg, &ahp);
        if (hp == NULL)
-               return RESULT_SHOWUSAGE;
+               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(fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
+               ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
        else
-               ast_cli(fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
+               ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
        udptldebug = 1;
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 }
 
-static int udptl_do_debug(int fd, int argc, char *argv[])
+static char *handle_cli_udptl_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       if (argc != 2) {
-               if (argc != 4)
-                       return RESULT_SHOWUSAGE;
-               return udptl_do_debug_ip(fd, argc, argv);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "udptl debug";
+               e->usage =
+                       "Usage: udptl debug\n"
+                       "       Enable dumping of all UDPTL packets.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
        }
+
+       if (a->argc != 2)
+               return CLI_SHOWUSAGE;
+
        udptldebug = 1;
-       memset(&udptldebugaddr,0,sizeof(udptldebugaddr));
-       ast_cli(fd, "UDPTL Debugging Enabled\n");
-       return RESULT_SUCCESS;
-}
+       memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
 
-static int udptl_no_debug(int fd, int argc, char *argv[])
-{
-       if (argc !=3)
-               return RESULT_SHOWUSAGE;
-       udptldebug = 0;
-       ast_cli(fd,"UDPTL Debugging Disabled\n");
-       return RESULT_SUCCESS;
+       ast_cli(a->fd, "UDPTL Debugging Enabled\n");
+       return CLI_SUCCESS;
 }
 
-static char debug_usage[] =
-  "Usage: udptl debug [ip host[:port]]\n"
-  "       Enable dumping of all UDPTL packets to and from host.\n";
+static char *handle_cli_udptl_debug_off(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "udptl debug off";
+               e->usage =
+                       "Usage: udptl debug off\n"
+                       "       Disable dumping of all UDPTL packets.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-static char no_debug_usage[] =
-  "Usage: udptl no debug\n"
-  "       Disable all UDPTL debugging\n";
+       if (a->argc != 3)
+               return CLI_SHOWUSAGE;
 
-static struct ast_cli_entry cli_debug_ip =
-{{ "udptl", "debug", "ip", NULL } , udptl_do_debug, "Enable UDPTL debugging on IP", debug_usage };
+       udptldebug = 0;
 
-static struct ast_cli_entry cli_debug =
-{{ "udptl", "debug", NULL } , udptl_do_debug, "Enable UDPTL debugging", debug_usage };
+       ast_cli(a->fd, "UDPTL Debugging Disabled\n");
+       return CLI_SUCCESS;
+}
 
-static struct ast_cli_entry cli_no_debug =
-{{ "udptl", "no", "debug", NULL } , udptl_no_debug, "Disable UDPTL debugging", no_debug_usage };
+static struct ast_cli_entry cli_udptl[] = {
+       AST_CLI_DEFINE(handle_cli_udptl_debug,     "Enable UDPTL debugging"),
+       AST_CLI_DEFINE(handle_cli_udptl_debug_ip,  "Enable UDPTL debugging on IP"),
+       AST_CLI_DEFINE(handle_cli_udptl_debug_off, "Disable UDPTL debugging")
+};
 
-void ast_udptl_reload(void)
+static void __ast_udptl_reload(int reload)
 {
        struct ast_config *cfg;
-       char *s;
+       const char *s;
+       struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+
+       if ((cfg = ast_config_load("udptl.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
+               return;
 
        udptlstart = 4500;
        udptlend = 4999;
@@ -1182,7 +1205,7 @@ void ast_udptl_reload(void)
        udptlfecspan = 0;
        udptlmaxdatagram = 0;
 
-       if ((cfg = ast_config_load("udptl.conf"))) {
+       if (cfg) {
                if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) {
                        udptlstart = atoi(s);
                        if (udptlstart < 1024)
@@ -1242,14 +1265,16 @@ void ast_udptl_reload(void)
                udptlstart = 4500;
                udptlend = 4999;
        }
-       if (option_verbose > 1)
-               ast_verbose(VERBOSE_PREFIX_2 "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
+       ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
+}
+
+void ast_udptl_reload(void)
+{
+       __ast_udptl_reload(1);
 }
 
 void ast_udptl_init(void)
 {
-       ast_cli_register(&cli_debug);
-       ast_cli_register(&cli_debug_ip);
-       ast_cli_register(&cli_no_debug);
-       ast_udptl_reload();
+       ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry));
+       __ast_udptl_reload(0);
 }