Merged revisions 175311 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.4

........
  r175311 | tilghman | 2009-02-12 15:19:40 -0600 (Thu, 12 Feb 2009) | 9 lines
  
  Fix crashes when receiving certain T.38 packets.  Also, increase the maximum
  size of T.38 packets and warn users when they try to set the limits above those
  maximums.
  (closes issue #13050)
   Reported by: schern
   Patches: 
         20090212__bug13050.diff.txt uploaded by Corydon76 (license 14)
   Tested by: schern
........


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@175334 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Tilghman Lesher 2009-02-12 21:25:14 +00:00
parent a46d290802
commit 9e0f5d2afe
1 changed files with 51 additions and 23 deletions

View File

@ -86,7 +86,7 @@ static int udptlfecentries;
static int udptlfecspan;
static int udptlmaxdatagram;
#define LOCAL_FAX_MAX_DATAGRAM 400
#define LOCAL_FAX_MAX_DATAGRAM 1400
#define MAX_FEC_ENTRIES 5
#define MAX_FEC_SPAN 5
@ -159,7 +159,7 @@ struct ast_udptl {
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);
static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, int buflen, uint8_t *ifp, int ifp_len);
static inline int udptl_debug_test_addr(struct sockaddr_in *addr)
{
@ -257,7 +257,7 @@ static int encode_length(uint8_t *buf, int *len, int value)
}
/*- End of function --------------------------------------------------------*/
static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num_octets)
static int encode_open_type(uint8_t *buf, int buflen, int *len, const uint8_t *data, int num_octets)
{
int enclen;
int octet_idx;
@ -273,6 +273,10 @@ static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num
for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
if ((enclen = encode_length(buf, len, num_octets)) < 0)
return -1;
if (enclen + *len > buflen) {
ast_log(LOG_ERROR, "Buffer overflow detected (%d + %d > %d)\n", enclen, *len, buflen);
return -1;
}
if (enclen > 0) {
memcpy(&buf[*len], &data[octet_idx], enclen);
*len += enclen;
@ -493,9 +497,9 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
}
/*- End of function --------------------------------------------------------*/
static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len)
static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, int buflen, uint8_t *ifp, int ifp_len)
{
uint8_t fec[LOCAL_FAX_MAX_DATAGRAM];
uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2];
int i;
int j;
int seq;
@ -525,7 +529,7 @@ static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, i
buf[len++] = seq & 0xFF;
/* Encode the primary IFP packet */
if (encode_open_type(buf, &len, ifp, ifp_len) < 0)
if (encode_open_type(buf, buflen, &len, ifp, ifp_len) < 0)
return -1;
/* Encode the appropriate type of error recovery information */
@ -553,8 +557,12 @@ static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, i
/* Encode the elements */
for (i = 0; i < entries; i++) {
j = (entry - i - 1) & UDPTL_BUF_MASK;
if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0)
if (encode_open_type(buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) {
if (option_debug) {
ast_log(LOG_DEBUG, "Encoding failed at i=%d, j=%d\n", i, j);
}
return -1;
}
}
break;
case UDPTL_ERROR_CORRECTION_FEC:
@ -591,7 +599,7 @@ static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, i
fec[j] ^= s->tx[i].buf[j];
}
}
if (encode_open_type(buf, &len, fec, high_tide) < 0)
if (encode_open_type(buf, buflen, &len, fec, high_tide) < 0)
return -1;
}
break;
@ -888,7 +896,7 @@ int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
int seq;
int len;
int res;
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM * 2];
/* If we have no peer, return immediately */
if (s->them.sin_addr.s_addr == INADDR_ANY)
@ -907,7 +915,7 @@ int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
seq = s->tx_seq_no & 0xFFFF;
/* Cook up the UDPTL packet, with the relevant EC info. */
len = udptl_build_packet(s, buf, f->data.ptr, f->datalen);
len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, f->datalen);
if (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)
@ -1175,17 +1183,25 @@ static void __ast_udptl_reload(int reload)
if (cfg) {
if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) {
udptlstart = atoi(s);
if (udptlstart < 1024)
if (udptlstart < 1024) {
ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n");
udptlstart = 1024;
if (udptlstart > 65535)
}
if (udptlstart > 65535) {
ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n");
udptlstart = 65535;
}
}
if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) {
udptlend = atoi(s);
if (udptlend < 1024)
if (udptlend < 1024) {
ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n");
udptlend = 1024;
if (udptlend > 65535)
}
if (udptlend > 65535) {
ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n");
udptlend = 65535;
}
}
if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) {
#ifdef SO_NO_CHECK
@ -1206,24 +1222,36 @@ static void __ast_udptl_reload(int reload)
}
if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) {
udptlmaxdatagram = atoi(s);
if (udptlmaxdatagram < 0)
udptlmaxdatagram = 0;
if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM)
if (udptlmaxdatagram < 100) {
ast_log(LOG_WARNING, "Too small T38FaxMaxDatagram size. Defaulting to 100.\n");
udptlmaxdatagram = 100;
}
if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM) {
ast_log(LOG_WARNING, "Too large T38FaxMaxDatagram size. Defaulting to %d.\n", LOCAL_FAX_MAX_DATAGRAM);
udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM;
}
}
if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) {
udptlfecentries = atoi(s);
if (udptlfecentries < 0)
udptlfecentries = 0;
if (udptlfecentries > MAX_FEC_ENTRIES)
if (udptlfecentries < 1) {
ast_log(LOG_WARNING, "Too small UDPTLFECentries value. Defaulting to 1.\n");
udptlfecentries = 1;
}
if (udptlfecentries > MAX_FEC_ENTRIES) {
ast_log(LOG_WARNING, "Too large UDPTLFECentries value. Defaulting to %d.\n", MAX_FEC_ENTRIES);
udptlfecentries = MAX_FEC_ENTRIES;
}
}
if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) {
udptlfecspan = atoi(s);
if (udptlfecspan < 0)
udptlfecspan = 0;
if (udptlfecspan > MAX_FEC_SPAN)
if (udptlfecspan < 1) {
ast_log(LOG_WARNING, "Too small UDPTLFECspan value. Defaulting to 1.\n");
udptlfecspan = 1;
}
if (udptlfecspan > MAX_FEC_SPAN) {
ast_log(LOG_WARNING, "Too large UDPTLFECspan value. Defaulting to %d.\n", MAX_FEC_SPAN);
udptlfecspan = MAX_FEC_SPAN;
}
}
ast_config_destroy(cfg);
}