Add the ability to dynamically specify weights for responses to DUNDi queries.
[asterisk/asterisk.git] / main / udptl.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * UDPTL support for T.38
5  * 
6  * Copyright (C) 2005, Steve Underwood, partly based on RTP code which is
7  * Copyright (C) 1999-2006, Digium, Inc.
8  *
9  * Steve Underwood <steveu@coppice.org>
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  *
21  * A license has been granted to Digium (via disclaimer) for the use of
22  * this code.
23  */
24
25 /*! 
26  * \file 
27  *
28  * \brief UDPTL support for T.38 faxing
29  * 
30  *
31  * \author Mark Spencer <markster@digium.com>,  Steve Underwood <steveu@coppice.org>
32  * 
33  * \page T38fax_udptl T38 fax passhtrough :: UDPTL
34  *
35  * Asterisk supports T.38 fax passthrough. Asterisk will not be a client, server
36  * or any form of gateway. Currently fax passthrough is only implemented in the
37  * SIP channel for strict SIP to SIP calls. If you are using chan_local or chan_agent
38  * as a proxy channel, T.38 passthrough will not work.
39  *
40  * UDPTL is handled very much like RTP. It can be reinvited to go directly between
41  * the endpoints, without involving Asterisk in the media stream.
42  * 
43  * \b References:
44  * - chan_sip.c
45  * - udptl.c
46  */
47
48
49 #include "asterisk.h"
50
51 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <sys/time.h>
57 #include <signal.h>
58 #include <errno.h>
59 #include <unistd.h>
60 #include <netinet/in.h>
61 #include <sys/time.h>
62 #include <sys/socket.h>
63 #include <arpa/inet.h>
64 #include <fcntl.h>
65
66 #include "asterisk/udptl.h"
67 #include "asterisk/frame.h"
68 #include "asterisk/logger.h"
69 #include "asterisk/options.h"
70 #include "asterisk/channel.h"
71 #include "asterisk/acl.h"
72 #include "asterisk/channel.h"
73 #include "asterisk/config.h"
74 #include "asterisk/lock.h"
75 #include "asterisk/utils.h"
76 #include "asterisk/cli.h"
77 #include "asterisk/unaligned.h"
78 #include "asterisk/utils.h"
79
80 #define UDPTL_MTU               1200
81
82 #if !defined(FALSE)
83 #define FALSE 0
84 #endif
85 #if !defined(TRUE)
86 #define TRUE (!FALSE)
87 #endif
88
89 static int udptlstart;
90 static int udptlend;
91 static int udptldebug;                      /*!< Are we debugging? */
92 static struct sockaddr_in udptldebugaddr;   /*!< Debug packets to/from this host */
93 #ifdef SO_NO_CHECK
94 static int nochecksums;
95 #endif
96 static int udptlfectype;
97 static int udptlfecentries;
98 static int udptlfecspan;
99 static int udptlmaxdatagram;
100
101 #define LOCAL_FAX_MAX_DATAGRAM      400
102 #define MAX_FEC_ENTRIES             5
103 #define MAX_FEC_SPAN                5
104
105 #define UDPTL_BUF_MASK              15
106
107 typedef struct {
108         int buf_len;
109         uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
110 } udptl_fec_tx_buffer_t;
111
112 typedef struct {
113         int buf_len;
114         uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
115         int fec_len[MAX_FEC_ENTRIES];
116         uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM];
117         int fec_span;
118         int fec_entries;
119 } udptl_fec_rx_buffer_t;
120
121 /*! \brief Structure for an UDPTL session */
122 struct ast_udptl {
123         int fd;
124         char resp;
125         struct ast_frame f[16];
126         unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
127         unsigned int lasteventseqn;
128         int nat;
129         int flags;
130         struct sockaddr_in us;
131         struct sockaddr_in them;
132         int *ioid;
133         uint16_t seqno;
134         struct sched_context *sched;
135         struct io_context *io;
136         void *data;
137         ast_udptl_callback callback;
138         int udptl_offered_from_local;
139
140         /*! This option indicates the error correction scheme used in transmitted UDPTL
141             packets. */
142         int error_correction_scheme;
143
144         /*! This option indicates the number of error correction entries transmitted in
145             UDPTL packets. */
146         int error_correction_entries;
147
148         /*! This option indicates the span of the error correction entries in transmitted
149             UDPTL packets (FEC only). */
150         int error_correction_span;
151
152         /*! This option indicates the maximum size of a UDPTL packet that can be accepted by
153             the remote device. */
154         int far_max_datagram_size;
155
156         /*! This option indicates the maximum size of a UDPTL packet that we are prepared to
157             accept. */
158         int local_max_datagram_size;
159
160         int verbose;
161
162         struct sockaddr_in far;
163
164         int tx_seq_no;
165         int rx_seq_no;
166         int rx_expected_seq_no;
167
168         udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1];
169         udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
170 };
171
172 static struct ast_udptl_protocol *protos;
173
174 static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len);
175 static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len);
176
177 static inline int udptl_debug_test_addr(struct sockaddr_in *addr)
178 {
179         if (udptldebug == 0)
180                 return 0;
181         if (udptldebugaddr.sin_addr.s_addr) {
182                 if (((ntohs(udptldebugaddr.sin_port) != 0)
183                         && (udptldebugaddr.sin_port != addr->sin_port))
184                         || (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
185                         return 0;
186         }
187         return 1;
188 }
189
190 static int decode_length(uint8_t *buf, int limit, int *len, int *pvalue)
191 {
192         if ((buf[*len] & 0x80) == 0) {
193                 if (*len >= limit)
194                         return -1;
195                 *pvalue = buf[*len];
196                 (*len)++;
197                 return 0;
198         }
199         if ((buf[*len] & 0x40) == 0) {
200                 if (*len >= limit - 1)
201                         return -1;
202                 *pvalue = (buf[*len] & 0x3F) << 8;
203                 (*len)++;
204                 *pvalue |= buf[*len];
205                 (*len)++;
206                 return 0;
207         }
208         if (*len >= limit)
209                 return -1;
210         *pvalue = (buf[*len] & 0x3F) << 14;
211         (*len)++;
212         /* Indicate we have a fragment */
213         return 1;
214 }
215 /*- End of function --------------------------------------------------------*/
216
217 static int decode_open_type(uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets)
218 {
219         int octet_cnt;
220         int octet_idx;
221         int stat;
222         int i;
223         const uint8_t **pbuf;
224
225         for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) {
226                 if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0)
227                         return -1;
228                 if (octet_cnt > 0) {
229                         *p_num_octets += octet_cnt;
230
231                         pbuf = &p_object[octet_idx];
232                         i = 0;
233                         /* Make sure the buffer contains at least the number of bits requested */
234                         if ((*len + octet_cnt) > limit)
235                                 return -1;
236
237                         *pbuf = &buf[*len];
238                         *len += octet_cnt;
239                 }
240                 if (stat == 0)
241                         break;
242         }
243         return 0;
244 }
245 /*- End of function --------------------------------------------------------*/
246
247 static int encode_length(uint8_t *buf, int *len, int value)
248 {
249         int multiplier;
250
251         if (value < 0x80) {
252                 /* 1 octet */
253                 buf[*len] = value;
254                 (*len)++;
255                 return value;
256         }
257         if (value < 0x4000) {
258                 /* 2 octets */
259                 /* Set the first bit of the first octet */
260                 buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
261                 (*len)++;
262                 buf[*len] = value & 0xFF;
263                 (*len)++;
264                 return value;
265         }
266         /* Fragmentation */
267         multiplier = (value < 0x10000) ? (value >> 14) : 4;
268         /* Set the first 2 bits of the octet */
269         buf[*len] = 0xC0 | multiplier;
270         (*len)++;
271         return multiplier << 14;
272 }
273 /*- End of function --------------------------------------------------------*/
274
275 static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num_octets)
276 {
277         int enclen;
278         int octet_idx;
279         uint8_t zero_byte;
280
281         /* If open type is of zero length, add a single zero byte (10.1) */
282         if (num_octets == 0) {
283                 zero_byte = 0;
284                 data = &zero_byte;
285                 num_octets = 1;
286         }
287         /* Encode the open type */
288         for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
289                 if ((enclen = encode_length(buf, len, num_octets)) < 0)
290                         return -1;
291                 if (enclen > 0) {
292                         memcpy(&buf[*len], &data[octet_idx], enclen);
293                         *len += enclen;
294                 }
295                 if (enclen >= num_octets)
296                         break;
297         }
298
299         return 0;
300 }
301 /*- End of function --------------------------------------------------------*/
302
303 static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
304 {
305         int stat;
306         int stat2;
307         int i;
308         int j;
309         int k;
310         int l;
311         int m;
312         int x;
313         int limit;
314         int which;
315         int ptr;
316         int count;
317         int total_count;
318         int seq_no;
319         const uint8_t *ifp;
320         const uint8_t *data;
321         int ifp_len;
322         int repaired[16];
323         const uint8_t *bufs[16];
324         int lengths[16];
325         int span;
326         int entries;
327         int ifp_no;
328
329         ptr = 0;
330         ifp_no = 0;
331         memset(&s->f[0], 0, sizeof(s->f[0]));
332
333         /* Decode seq_number */
334         if (ptr + 2 > len)
335                 return -1;
336         seq_no = (buf[0] << 8) | buf[1];
337         ptr += 2;
338
339         /* Break out the primary packet */
340         if ((stat = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0)
341                 return -1;
342         /* Decode error_recovery */
343         if (ptr + 1 > len)
344                 return -1;
345         if ((buf[ptr++] & 0x80) == 0) {
346                 /* Secondary packet mode for error recovery */
347                 if (seq_no > s->rx_seq_no) {
348                         /* We received a later packet than we expected, so we need to check if we can fill in the gap from the
349                            secondary packets. */
350                         total_count = 0;
351                         do {
352                                 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
353                                         return -1;
354                                 for (i = 0; i < count; i++) {
355                                         if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0)
356                                                 return -1;
357                                 }
358                                 total_count += count;
359                         }
360                         while (stat2 > 0);
361                         /* Step through in reverse order, so we go oldest to newest */
362                         for (i = total_count; i > 0; i--) {
363                                 if (seq_no - i >= s->rx_seq_no) {
364                                         /* This one wasn't seen before */
365                                         /* Decode the secondary IFP packet */
366                                         //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]);
367                                         s->f[ifp_no].frametype = AST_FRAME_MODEM;
368                                         s->f[ifp_no].subclass = AST_MODEM_T38;
369
370                                         s->f[ifp_no].mallocd = 0;
371                                         //s->f[ifp_no].???seq_no = seq_no - i;
372                                         s->f[ifp_no].datalen = lengths[i - 1];
373                                         s->f[ifp_no].data = (uint8_t *) bufs[i - 1];
374                                         s->f[ifp_no].offset = 0;
375                                         s->f[ifp_no].src = "UDPTL";
376                                         if (ifp_no > 0)
377                                                 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
378                                         AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
379                                         ifp_no++;
380                                 }
381                         }
382                 }
383                 /* If packets are received out of sequence, we may have already processed this packet from the error
384                    recovery information in a packet already received. */
385                 if (seq_no >= s->rx_seq_no) {
386                         /* Decode the primary IFP packet */
387                         s->f[ifp_no].frametype = AST_FRAME_MODEM;
388                         s->f[ifp_no].subclass = AST_MODEM_T38;
389                         
390                         s->f[ifp_no].mallocd = 0;
391                         //s->f[ifp_no].???seq_no = seq_no;
392                         s->f[ifp_no].datalen = ifp_len;
393                         s->f[ifp_no].data = (uint8_t *) ifp;
394                         s->f[ifp_no].offset = 0;
395                         s->f[ifp_no].src = "UDPTL";
396                         if (ifp_no > 0)
397                                 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
398                         AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
399                 }
400         }
401         else
402         {
403                 /* FEC mode for error recovery */
404                 /* Our buffers cannot tolerate overlength IFP packets in FEC mode */
405                 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM)
406                         return -1;
407                 /* Update any missed slots in the buffer */
408                 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) {
409                         x = s->rx_seq_no & UDPTL_BUF_MASK;
410                         s->rx[x].buf_len = -1;
411                         s->rx[x].fec_len[0] = 0;
412                         s->rx[x].fec_span = 0;
413                         s->rx[x].fec_entries = 0;
414                 }
415
416                 x = seq_no & UDPTL_BUF_MASK;
417
418                 memset(repaired, 0, sizeof(repaired));
419
420                 /* Save the new IFP packet */
421                 memcpy(s->rx[x].buf, ifp, ifp_len);
422                 s->rx[x].buf_len = ifp_len;
423                 repaired[x] = TRUE;
424
425                 /* Decode the FEC packets */
426                 /* The span is defined as an unconstrained integer, but will never be more
427                    than a small value. */
428                 if (ptr + 2 > len)
429                         return -1;
430                 if (buf[ptr++] != 1)
431                         return -1;
432                 span = buf[ptr++];
433                 s->rx[x].fec_span = span;
434
435                 /* The number of entries is defined as a length, but will only ever be a small
436                    value. Treat it as such. */
437                 if (ptr + 1 > len)
438                         return -1;
439                 entries = buf[ptr++];
440                 s->rx[x].fec_entries = entries;
441
442                 /* Decode the elements */
443                 for (i = 0; i < entries; i++) {
444                         if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
445                                 return -1;
446                         if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM)
447                                 return -1;
448
449                         /* Save the new FEC data */
450                         memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
451 #if 0
452                         fprintf(stderr, "FEC: ");
453                         for (j = 0; j < s->rx[x].fec_len[i]; j++)
454                                 fprintf(stderr, "%02X ", data[j]);
455                         fprintf(stderr, "\n");
456 #endif
457                 }
458
459                 /* See if we can reconstruct anything which is missing */
460                 /* TODO: this does not comprehensively hunt back and repair everything that is possible */
461                 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
462                         if (s->rx[l].fec_len[0] <= 0)
463                                 continue;
464                         for (m = 0; m < s->rx[l].fec_entries; m++) {
465                                 limit = (l + m) & UDPTL_BUF_MASK;
466                                 for (which = -1, k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) {
467                                         if (s->rx[k].buf_len <= 0)
468                                                 which = (which == -1) ? k : -2;
469                                 }
470                                 if (which >= 0) {
471                                         /* Repairable */
472                                         for (j = 0; j < s->rx[l].fec_len[m]; j++) {
473                                                 s->rx[which].buf[j] = s->rx[l].fec[m][j];
474                                                 for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
475                                                         s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
476                                         }
477                                         s->rx[which].buf_len = s->rx[l].fec_len[m];
478                                         repaired[which] = TRUE;
479                                 }
480                         }
481                 }
482                 /* Now play any new packets forwards in time */
483                 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) {
484                         if (repaired[l]) {
485                                 //fprintf(stderr, "Fixed packet %d, len %d\n", j, l);
486                                 s->f[ifp_no].frametype = AST_FRAME_MODEM;
487                                 s->f[ifp_no].subclass = AST_MODEM_T38;
488                         
489                                 s->f[ifp_no].mallocd = 0;
490                                 //s->f[ifp_no].???seq_no = j;
491                                 s->f[ifp_no].datalen = s->rx[l].buf_len;
492                                 s->f[ifp_no].data = s->rx[l].buf;
493                                 s->f[ifp_no].offset = 0;
494                                 s->f[ifp_no].src = "UDPTL";
495                                 if (ifp_no > 0)
496                                         AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
497                                 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
498                                 ifp_no++;
499                         }
500                 }
501                 /* Decode the primary IFP packet */
502                 s->f[ifp_no].frametype = AST_FRAME_MODEM;
503                 s->f[ifp_no].subclass = AST_MODEM_T38;
504                         
505                 s->f[ifp_no].mallocd = 0;
506                 //s->f[ifp_no].???seq_no = j;
507                 s->f[ifp_no].datalen = ifp_len;
508                 s->f[ifp_no].data = (uint8_t *) ifp;
509                 s->f[ifp_no].offset = 0;
510                 s->f[ifp_no].src = "UDPTL";
511                 if (ifp_no > 0)
512                         AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
513                 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
514         }
515
516         s->rx_seq_no = seq_no + 1;
517         return 0;
518 }
519 /*- End of function --------------------------------------------------------*/
520
521 static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len)
522 {
523         uint8_t fec[LOCAL_FAX_MAX_DATAGRAM];
524         int i;
525         int j;
526         int seq;
527         int entry;
528         int entries;
529         int span;
530         int m;
531         int len;
532         int limit;
533         int high_tide;
534
535         seq = s->tx_seq_no & 0xFFFF;
536
537         /* Map the sequence number to an entry in the circular buffer */
538         entry = seq & UDPTL_BUF_MASK;
539
540         /* We save the message in a circular buffer, for generating FEC or
541            redundancy sets later on. */
542         s->tx[entry].buf_len = ifp_len;
543         memcpy(s->tx[entry].buf, ifp, ifp_len);
544         
545         /* Build the UDPTLPacket */
546
547         len = 0;
548         /* Encode the sequence number */
549         buf[len++] = (seq >> 8) & 0xFF;
550         buf[len++] = seq & 0xFF;
551
552         /* Encode the primary IFP packet */
553         if (encode_open_type(buf, &len, ifp, ifp_len) < 0)
554                 return -1;
555
556         /* Encode the appropriate type of error recovery information */
557         switch (s->error_correction_scheme)
558         {
559         case UDPTL_ERROR_CORRECTION_NONE:
560                 /* Encode the error recovery type */
561                 buf[len++] = 0x00;
562                 /* The number of entries will always be zero, so it is pointless allowing
563                    for the fragmented case here. */
564                 if (encode_length(buf, &len, 0) < 0)
565                         return -1;
566                 break;
567         case UDPTL_ERROR_CORRECTION_REDUNDANCY:
568                 /* Encode the error recovery type */
569                 buf[len++] = 0x00;
570                 if (s->tx_seq_no > s->error_correction_entries)
571                         entries = s->error_correction_entries;
572                 else
573                         entries = s->tx_seq_no;
574                 /* The number of entries will always be small, so it is pointless allowing
575                    for the fragmented case here. */
576                 if (encode_length(buf, &len, entries) < 0)
577                         return -1;
578                 /* Encode the elements */
579                 for (i = 0; i < entries; i++) {
580                         j = (entry - i - 1) & UDPTL_BUF_MASK;
581                         if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0)
582                                 return -1;
583                 }
584                 break;
585         case UDPTL_ERROR_CORRECTION_FEC:
586                 span = s->error_correction_span;
587                 entries = s->error_correction_entries;
588                 if (seq < s->error_correction_span*s->error_correction_entries) {
589                         /* In the initial stages, wind up the FEC smoothly */
590                         entries = seq/s->error_correction_span;
591                         if (seq < s->error_correction_span)
592                                 span = 0;
593                 }
594                 /* Encode the error recovery type */
595                 buf[len++] = 0x80;
596                 /* Span is defined as an inconstrained integer, which it dumb. It will only
597                    ever be a small value. Treat it as such. */
598                 buf[len++] = 1;
599                 buf[len++] = span;
600                 /* The number of entries is defined as a length, but will only ever be a small
601                    value. Treat it as such. */
602                 buf[len++] = entries;
603                 for (m = 0; m < entries; m++) {
604                         /* Make an XOR'ed entry the maximum length */
605                         limit = (entry + m) & UDPTL_BUF_MASK;
606                         high_tide = 0;
607                         for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
608                                 if (high_tide < s->tx[i].buf_len) {
609                                         for (j = 0; j < high_tide; j++)
610                                                 fec[j] ^= s->tx[i].buf[j];
611                                         for ( ; j < s->tx[i].buf_len; j++)
612                                                 fec[j] = s->tx[i].buf[j];
613                                         high_tide = s->tx[i].buf_len;
614                                 } else {
615                                         for (j = 0; j < s->tx[i].buf_len; j++)
616                                                 fec[j] ^= s->tx[i].buf[j];
617                                 }
618                         }
619                         if (encode_open_type(buf, &len, fec, high_tide) < 0)
620                                 return -1;
621                 }
622                 break;
623         }
624
625         if (s->verbose)
626                 fprintf(stderr, "\n");
627
628         s->tx_seq_no++;
629         return len;
630 }
631
632 int ast_udptl_fd(struct ast_udptl *udptl)
633 {
634         return udptl->fd;
635 }
636
637 void ast_udptl_set_data(struct ast_udptl *udptl, void *data)
638 {
639         udptl->data = data;
640 }
641
642 void ast_udptl_set_callback(struct ast_udptl *udptl, ast_udptl_callback callback)
643 {
644         udptl->callback = callback;
645 }
646
647 void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
648 {
649         udptl->nat = nat;
650 }
651
652 static int udptlread(int *id, int fd, short events, void *cbdata)
653 {
654         struct ast_udptl *udptl = cbdata;
655         struct ast_frame *f;
656
657         if ((f = ast_udptl_read(udptl))) {
658                 if (udptl->callback)
659                         udptl->callback(udptl, f, udptl->data);
660         }
661         return 1;
662 }
663
664 struct ast_frame *ast_udptl_read(struct ast_udptl *udptl)
665 {
666         int res;
667         struct sockaddr_in sin;
668         socklen_t len;
669         uint16_t seqno = 0;
670         uint16_t *udptlheader;
671
672         len = sizeof(sin);
673         
674         /* Cache where the header will go */
675         res = recvfrom(udptl->fd,
676                         udptl->rawdata + AST_FRIENDLY_OFFSET,
677                         sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
678                         0,
679                         (struct sockaddr *) &sin,
680                         &len);
681         udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET);
682         if (res < 0) {
683                 if (errno != EAGAIN)
684                         ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno));
685                 if (errno == EBADF)
686                         CRASH;
687                 return &ast_null_frame;
688         }
689
690         /* Ignore if the other side hasn't been given an address yet. */
691         if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port)
692                 return &ast_null_frame;
693
694         if (udptl->nat) {
695                 /* Send to whoever sent to us */
696                 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
697                         (udptl->them.sin_port != sin.sin_port)) {
698                         memcpy(&udptl->them, &sin, sizeof(udptl->them));
699                         if (option_debug)
700                                 ast_log(LOG_DEBUG, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
701                 }
702         }
703
704         if (udptl_debug_test_addr(&sin)) {
705                 if (option_verbose)
706                         ast_verbose("Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n",
707                                 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res);
708         }
709 #if 0
710         printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res);
711 #endif
712         udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res);
713
714         return &udptl->f[0];
715 }
716
717 void ast_udptl_offered_from_local(struct ast_udptl* udptl, int local)
718 {
719         if (udptl)
720                 udptl->udptl_offered_from_local = local;
721         else
722                 ast_log(LOG_WARNING, "udptl structure is null\n");
723 }
724
725 int ast_udptl_get_error_correction_scheme(struct ast_udptl* udptl)
726 {
727         if (udptl)
728                 return udptl->error_correction_scheme;
729         else {
730                 ast_log(LOG_WARNING, "udptl structure is null\n");
731                 return -1;
732         }
733 }
734
735 void ast_udptl_set_error_correction_scheme(struct ast_udptl* udptl, int ec)
736 {
737         if (udptl) {
738                 switch (ec) {
739                 case UDPTL_ERROR_CORRECTION_FEC:
740                         udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
741                         break;
742                 case UDPTL_ERROR_CORRECTION_REDUNDANCY:
743                         udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
744                         break;
745                 case UDPTL_ERROR_CORRECTION_NONE:
746                         udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE;
747                         break;
748                 default:
749                         ast_log(LOG_WARNING, "error correction parameter invalid\n");
750                 };
751         } else
752                 ast_log(LOG_WARNING, "udptl structure is null\n");
753 }
754
755 int ast_udptl_get_local_max_datagram(struct ast_udptl* udptl)
756 {
757         if (udptl)
758                 return udptl->local_max_datagram_size;
759         else {
760                 ast_log(LOG_WARNING, "udptl structure is null\n");
761                 return -1;
762         }
763 }
764
765 int ast_udptl_get_far_max_datagram(struct ast_udptl* udptl)
766 {
767         if (udptl)
768                 return udptl->far_max_datagram_size;
769         else {
770                 ast_log(LOG_WARNING, "udptl structure is null\n");
771                 return -1;
772         }
773 }
774
775 void ast_udptl_set_local_max_datagram(struct ast_udptl* udptl, int max_datagram)
776 {
777         if (udptl)
778                 udptl->local_max_datagram_size = max_datagram;
779         else
780                 ast_log(LOG_WARNING, "udptl structure is null\n");
781 }
782
783 void ast_udptl_set_far_max_datagram(struct ast_udptl* udptl, int max_datagram)
784 {
785         if (udptl)
786                 udptl->far_max_datagram_size = max_datagram;
787         else
788                 ast_log(LOG_WARNING, "udptl structure is null\n");
789 }
790
791 struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr)
792 {
793         struct ast_udptl *udptl;
794         int x;
795         int startplace;
796         int i;
797         long int flags;
798
799         if (!(udptl = ast_calloc(1, sizeof(*udptl))))
800                 return NULL;
801
802         if (udptlfectype == 2)
803                 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
804         else if (udptlfectype == 1)
805                 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
806         else
807                 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE;
808         udptl->error_correction_span = udptlfecspan;
809         udptl->error_correction_entries = udptlfecentries;
810         
811         udptl->far_max_datagram_size = udptlmaxdatagram;
812         udptl->local_max_datagram_size = udptlmaxdatagram;
813
814         memset(&udptl->rx, 0, sizeof(udptl->rx));
815         memset(&udptl->tx, 0, sizeof(udptl->tx));
816         for (i = 0; i <= UDPTL_BUF_MASK; i++) {
817                 udptl->rx[i].buf_len = -1;
818                 udptl->tx[i].buf_len = -1;
819         }
820
821         udptl->seqno = ast_random() & 0xffff;
822         udptl->them.sin_family = AF_INET;
823         udptl->us.sin_family = AF_INET;
824
825         if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
826                 free(udptl);
827                 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
828                 return NULL;
829         }
830         flags = fcntl(udptl->fd, F_GETFL);
831         fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK);
832 #ifdef SO_NO_CHECK
833         if (nochecksums)
834                 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
835 #endif
836         /* Find us a place */
837         x = (ast_random() % (udptlend - udptlstart)) + udptlstart;
838         startplace = x;
839         for (;;) {
840                 udptl->us.sin_port = htons(x);
841                 udptl->us.sin_addr = addr;
842                 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0)
843                         break;
844                 if (errno != EADDRINUSE) {
845                         ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
846                         close(udptl->fd);
847                         free(udptl);
848                         return NULL;
849                 }
850                 if (++x > udptlend)
851                         x = udptlstart;
852                 if (x == startplace) {
853                         ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
854                         close(udptl->fd);
855                         free(udptl);
856                         return NULL;
857                 }
858         }
859         if (io && sched && callbackmode) {
860                 /* Operate this one in a callback mode */
861                 udptl->sched = sched;
862                 udptl->io = io;
863                 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl);
864         }
865         return udptl;
866 }
867
868 struct ast_udptl *ast_udptl_new(struct sched_context *sched, struct io_context *io, int callbackmode)
869 {
870         struct in_addr ia;
871         memset(&ia, 0, sizeof(ia));
872         return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia);
873 }
874
875 int ast_udptl_settos(struct ast_udptl *udptl, int tos)
876 {
877         int res;
878
879         if ((res = setsockopt(udptl->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
880                 ast_log(LOG_WARNING, "UDPTL unable to set TOS to %d\n", tos);
881         return res;
882 }
883
884 void ast_udptl_set_peer(struct ast_udptl *udptl, struct sockaddr_in *them)
885 {
886         udptl->them.sin_port = them->sin_port;
887         udptl->them.sin_addr = them->sin_addr;
888 }
889
890 void ast_udptl_get_peer(struct ast_udptl *udptl, struct sockaddr_in *them)
891 {
892         them->sin_family = AF_INET;
893         them->sin_port = udptl->them.sin_port;
894         them->sin_addr = udptl->them.sin_addr;
895 }
896
897 void ast_udptl_get_us(struct ast_udptl *udptl, struct sockaddr_in *us)
898 {
899         memcpy(us, &udptl->us, sizeof(udptl->us));
900 }
901
902 void ast_udptl_stop(struct ast_udptl *udptl)
903 {
904         memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr));
905         memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port));
906 }
907
908 void ast_udptl_destroy(struct ast_udptl *udptl)
909 {
910         if (udptl->ioid)
911                 ast_io_remove(udptl->io, udptl->ioid);
912         if (udptl->fd > -1)
913                 close(udptl->fd);
914         free(udptl);
915 }
916
917 int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
918 {
919         int len;
920         int res;
921         uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
922
923         /* If we have no peer, return immediately */    
924         if (s->them.sin_addr.s_addr == INADDR_ANY)
925                 return 0;
926
927         /* If there is no data length, return immediately */
928         if (f->datalen == 0)
929                 return 0;
930         
931         if (f->frametype != AST_FRAME_MODEM) {
932                 ast_log(LOG_WARNING, "UDPTL can only send T.38 data\n");
933                 return -1;
934         }
935
936         /* Cook up the UDPTL packet, with the relevant EC info. */
937         len = udptl_build_packet(s, buf, f->data, f->datalen);
938
939         if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) {
940                 if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0)
941                         ast_log(LOG_NOTICE, "UDPTL Transmission error to %s:%d: %s\n", ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), strerror(errno));
942 #if 0
943                 printf("Sent %d bytes of UDPTL data to %s:%d\n", res, ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
944 #endif
945                 if (udptl_debug_test_addr(&s->them))
946                         ast_verbose("Sent UDPTL packet to %s:%d (type %d, seq %d, len %d)\n",
947                                         ast_inet_ntoa(s->them.sin_addr),
948                                         ntohs(s->them.sin_port), 0, s->seqno, len);
949         }
950                 
951         return 0;
952 }
953
954 void ast_udptl_proto_unregister(struct ast_udptl_protocol *proto)
955 {
956         struct ast_udptl_protocol *cur;
957         struct ast_udptl_protocol *prev;
958
959         cur = protos;
960         prev = NULL;
961         while (cur) {
962                 if (cur == proto) {
963                         if (prev)
964                                 prev->next = proto->next;
965                         else
966                                 protos = proto->next;
967                         return;
968                 }
969                 prev = cur;
970                 cur = cur->next;
971         }
972 }
973
974 int ast_udptl_proto_register(struct ast_udptl_protocol *proto)
975 {
976         struct ast_udptl_protocol *cur;
977
978         cur = protos;
979         while (cur) {
980                 if (cur->type == proto->type) {
981                         ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
982                         return -1;
983                 }
984                 cur = cur->next;
985         }
986         proto->next = protos;
987         protos = proto;
988         return 0;
989 }
990
991 static struct ast_udptl_protocol *get_proto(struct ast_channel *chan)
992 {
993         struct ast_udptl_protocol *cur;
994
995         cur = protos;
996         while (cur) {
997                 if (cur->type == chan->tech->type)
998                         return cur;
999                 cur = cur->next;
1000         }
1001         return NULL;
1002 }
1003
1004 int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
1005 {
1006         struct ast_frame *f;
1007         struct ast_channel *who;
1008         struct ast_channel *cs[3];
1009         struct ast_udptl *p0;
1010         struct ast_udptl *p1;
1011         struct ast_udptl_protocol *pr0;
1012         struct ast_udptl_protocol *pr1;
1013         struct sockaddr_in ac0;
1014         struct sockaddr_in ac1;
1015         struct sockaddr_in t0;
1016         struct sockaddr_in t1;
1017         void *pvt0;
1018         void *pvt1;
1019         int to;
1020         
1021         ast_channel_lock(c0);
1022         while (ast_channel_trylock(c1)) {
1023                 ast_channel_unlock(c0);
1024                 usleep(1);
1025                 ast_channel_lock(c0);
1026         }
1027         pr0 = get_proto(c0);
1028         pr1 = get_proto(c1);
1029         if (!pr0) {
1030                 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
1031                 ast_channel_unlock(c0);
1032                 ast_channel_unlock(c1);
1033                 return -1;
1034         }
1035         if (!pr1) {
1036                 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
1037                 ast_channel_unlock(c0);
1038                 ast_channel_unlock(c1);
1039                 return -1;
1040         }
1041         pvt0 = c0->tech_pvt;
1042         pvt1 = c1->tech_pvt;
1043         p0 = pr0->get_udptl_info(c0);
1044         p1 = pr1->get_udptl_info(c1);
1045         if (!p0 || !p1) {
1046                 /* Somebody doesn't want to play... */
1047                 ast_channel_unlock(c0);
1048                 ast_channel_unlock(c1);
1049                 return -2;
1050         }
1051         if (pr0->set_udptl_peer(c0, p1)) {
1052                 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
1053         } else {
1054                 /* Store UDPTL peer */
1055                 ast_udptl_get_peer(p1, &ac1);
1056         }
1057         if (pr1->set_udptl_peer(c1, p0))
1058                 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
1059         else {
1060                 /* Store UDPTL peer */
1061                 ast_udptl_get_peer(p0, &ac0);
1062         }
1063         ast_channel_unlock(c0);
1064         ast_channel_unlock(c1);
1065         cs[0] = c0;
1066         cs[1] = c1;
1067         cs[2] = NULL;
1068         for (;;) {
1069                 if ((c0->tech_pvt != pvt0) ||
1070                         (c1->tech_pvt != pvt1) ||
1071                         (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
1072                                 if (option_debug)
1073                                         ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
1074                                 /* Tell it to try again later */
1075                                 return -3;
1076                 }
1077                 to = -1;
1078                 ast_udptl_get_peer(p1, &t1);
1079                 ast_udptl_get_peer(p0, &t0);
1080                 if (inaddrcmp(&t1, &ac1)) {
1081                         if (option_debug) {
1082                                 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 
1083                                         c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port));
1084                                 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 
1085                                         c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port));
1086                         }
1087                         memcpy(&ac1, &t1, sizeof(ac1));
1088                 }
1089                 if (inaddrcmp(&t0, &ac0)) {
1090                         if (option_debug) {
1091                                 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 
1092                                         c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port));
1093                                 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 
1094                                         c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port));
1095                         }
1096                         memcpy(&ac0, &t0, sizeof(ac0));
1097                 }
1098                 who = ast_waitfor_n(cs, 2, &to);
1099                 if (!who) {
1100                         if (option_debug)
1101                                 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
1102                         /* check for hangup / whentohangup */
1103                         if (ast_check_hangup(c0) || ast_check_hangup(c1))
1104                                 break;
1105                         continue;
1106                 }
1107                 f = ast_read(who);
1108                 if (!f) {
1109                         *fo = f;
1110                         *rc = who;
1111                         if (option_debug)
1112                                 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
1113                         /* That's all we needed */
1114                         return 0;
1115                 } else {
1116                         if (f->frametype == AST_FRAME_MODEM) {
1117                                 /* Forward T.38 frames if they happen upon us */
1118                                 if (who == c0) {
1119                                         ast_write(c1, f);
1120                                 } else if (who == c1) {
1121                                         ast_write(c0, f);
1122                                 }
1123                         }
1124                         ast_frfree(f);
1125                 }
1126                 /* Swap priority. Not that it's a big deal at this point */
1127                 cs[2] = cs[0];
1128                 cs[0] = cs[1];
1129                 cs[1] = cs[2];
1130         }
1131         return -1;
1132 }
1133
1134 static int udptl_do_debug_ip(int fd, int argc, char *argv[])
1135 {
1136         struct hostent *hp;
1137         struct ast_hostent ahp;
1138         int port;
1139         char *p;
1140         char *arg;
1141
1142         port = 0;
1143         if (argc != 4)
1144                 return RESULT_SHOWUSAGE;
1145         arg = argv[3];
1146         p = strstr(arg, ":");
1147         if (p) {
1148                 *p = '\0';
1149                 p++;
1150                 port = atoi(p);
1151         }
1152         hp = ast_gethostbyname(arg, &ahp);
1153         if (hp == NULL)
1154                 return RESULT_SHOWUSAGE;
1155         udptldebugaddr.sin_family = AF_INET;
1156         memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
1157         udptldebugaddr.sin_port = htons(port);
1158         if (port == 0)
1159                 ast_cli(fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
1160         else
1161                 ast_cli(fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
1162         udptldebug = 1;
1163         return RESULT_SUCCESS;
1164 }
1165
1166 static int udptl_do_debug(int fd, int argc, char *argv[])
1167 {
1168         if (argc != 2) {
1169                 if (argc != 4)
1170                         return RESULT_SHOWUSAGE;
1171                 return udptl_do_debug_ip(fd, argc, argv);
1172         }
1173         udptldebug = 1;
1174         memset(&udptldebugaddr,0,sizeof(udptldebugaddr));
1175         ast_cli(fd, "UDPTL Debugging Enabled\n");
1176         return RESULT_SUCCESS;
1177 }
1178
1179 static int udptl_nodebug(int fd, int argc, char *argv[])
1180 {
1181         if (argc != 3)
1182                 return RESULT_SHOWUSAGE;
1183         udptldebug = 0;
1184         ast_cli(fd,"UDPTL Debugging Disabled\n");
1185         return RESULT_SUCCESS;
1186 }
1187
1188 static const char debug_usage[] =
1189   "Usage: udptl debug [ip host[:port]]\n"
1190   "       Enable dumping of all UDPTL packets to and from host.\n";
1191
1192 static const char nodebug_usage[] =
1193   "Usage: udptl debug off\n"
1194   "       Disable all UDPTL debugging\n";
1195
1196 static struct ast_cli_entry cli_udptl[] = {
1197         { { "udptl", "debug", NULL },
1198         udptl_do_debug, "Enable UDPTL debugging",
1199         debug_usage },
1200
1201         { { "udptl", "debug", "ip", NULL },
1202         udptl_do_debug, "Enable UDPTL debugging on IP",
1203         debug_usage },
1204
1205         { { "udptl", "debug", "off", NULL },
1206         udptl_nodebug, "Disable UDPTL debugging",
1207         nodebug_usage },
1208 };
1209
1210 void ast_udptl_reload(void)
1211 {
1212         struct ast_config *cfg;
1213         const char *s;
1214
1215         udptlstart = 4500;
1216         udptlend = 4999;
1217         udptlfectype = 0;
1218         udptlfecentries = 0;
1219         udptlfecspan = 0;
1220         udptlmaxdatagram = 0;
1221
1222         if ((cfg = ast_config_load("udptl.conf"))) {
1223                 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) {
1224                         udptlstart = atoi(s);
1225                         if (udptlstart < 1024)
1226                                 udptlstart = 1024;
1227                         if (udptlstart > 65535)
1228                                 udptlstart = 65535;
1229                 }
1230                 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) {
1231                         udptlend = atoi(s);
1232                         if (udptlend < 1024)
1233                                 udptlend = 1024;
1234                         if (udptlend > 65535)
1235                                 udptlend = 65535;
1236                 }
1237                 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) {
1238 #ifdef SO_NO_CHECK
1239                         if (ast_false(s))
1240                                 nochecksums = 1;
1241                         else
1242                                 nochecksums = 0;
1243 #else
1244                         if (ast_false(s))
1245                                 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
1246 #endif
1247                 }
1248                 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) {
1249                         if (strcmp(s, "t38UDPFEC") == 0)
1250                                 udptlfectype = 2;
1251                         else if (strcmp(s, "t38UDPRedundancy") == 0)
1252                                 udptlfectype = 1;
1253                 }
1254                 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) {
1255                         udptlmaxdatagram = atoi(s);
1256                         if (udptlmaxdatagram < 0)
1257                                 udptlmaxdatagram = 0;
1258                         if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM)
1259                                 udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM;
1260                 }
1261                 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) {
1262                         udptlfecentries = atoi(s);
1263                         if (udptlfecentries < 0)
1264                                 udptlfecentries = 0;
1265                         if (udptlfecentries > MAX_FEC_ENTRIES)
1266                                 udptlfecentries = MAX_FEC_ENTRIES;
1267                 }
1268                 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) {
1269                         udptlfecspan = atoi(s);
1270                         if (udptlfecspan < 0)
1271                                 udptlfecspan = 0;
1272                         if (udptlfecspan > MAX_FEC_SPAN)
1273                                 udptlfecspan = MAX_FEC_SPAN;
1274                 }
1275                 ast_config_destroy(cfg);
1276         }
1277         if (udptlstart >= udptlend) {
1278                 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n");
1279                 udptlstart = 4500;
1280                 udptlend = 4999;
1281         }
1282         if (option_verbose > 1)
1283                 ast_verbose(VERBOSE_PREFIX_2 "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
1284 }
1285
1286 void ast_udptl_init(void)
1287 {
1288         ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry));
1289         ast_udptl_reload();
1290 }