[asterisk-commits] dvossel: tag 1.6.0.22 r244386 - in /tags/1.6.0.22: channels/ include/asterisk...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Feb 2 13:57:49 CST 2010


Author: dvossel
Date: Tue Feb  2 13:57:47 2010
New Revision: 244386

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=244386
Log:
Fixes T38 crash with invalid FaxMaxDatagram field

AST-2010-001

Modified:
    tags/1.6.0.22/channels/chan_sip.c
    tags/1.6.0.22/include/asterisk/udptl.h
    tags/1.6.0.22/main/udptl.c

Modified: tags/1.6.0.22/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.0.22/channels/chan_sip.c?view=diff&rev=244386&r1=244385&r2=244386
==============================================================================
--- tags/1.6.0.22/channels/chan_sip.c (original)
+++ tags/1.6.0.22/channels/chan_sip.c Tue Feb  2 13:57:47 2010
@@ -3064,7 +3064,7 @@
 	p->packets = pkt;	/* Add it to the queue */
 	if (resp) {
 		/* Parse out the response code */
-		if (sscanf(pkt->data, "SIP/2.0 %30d", &respid) == 1) {
+		if (sscanf(pkt->data, "SIP/2.0 %30u", &respid) == 1) {
 			pkt->response_code = respid;
 		}
 	}
@@ -4220,20 +4220,30 @@
 		return;
 
 	/* Given the state requested and old state determine what control frame we want to queue up */
-	if (state == T38_PEER_REINVITE) {
+	switch (state) {
+	case T38_PEER_REINVITE:
 		parameters = p->t38.their_parms;
 		parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
 		parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
 		ast_udptl_set_tag(p->udptl, "SIP/%s", p->username);
-	} else if (state == T38_ENABLED) {
+		break;
+	case T38_ENABLED:
 		parameters = p->t38.their_parms;
 		parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
 		parameters.request_response = AST_T38_NEGOTIATED;
 		ast_udptl_set_tag(p->udptl, "SIP/%s", p->username);
-	} else if (state == T38_DISABLED && old == T38_ENABLED)
-		parameters.request_response = AST_T38_TERMINATED;
-	else if (state == T38_DISABLED && old == T38_LOCAL_REINVITE)
-		parameters.request_response = AST_T38_REFUSED;
+		break;
+	case T38_DISABLED:
+		if (old == T38_ENABLED) {
+			parameters.request_response = AST_T38_TERMINATED;
+		} else if (old == T38_LOCAL_REINVITE) {
+			parameters.request_response = AST_T38_REFUSED;
+		}
+		break;
+	case T38_LOCAL_REINVITE:
+		/* wait until we get a peer response before responding to local reinvite */
+		break;
+	}
 
 	/* Woot we got a message, create a control frame and send it on! */
 	if (parameters.request_response)
@@ -5534,10 +5544,22 @@
 /*! \brief Helper function which updates T.38 capability information and triggers a reinvite */
 static void interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_t38_parameters *parameters)
 {
+	if (!ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) {
+		return;
+	}
+
 	switch (parameters->request_response) {
 	case AST_T38_NEGOTIATED:
 	case AST_T38_REQUEST_NEGOTIATE:         /* Request T38 */
-		if (p->t38.state == T38_PEER_REINVITE) {
+		/* Negotiation can not take place without a valid max_ifp value. */
+		if (!parameters->max_ifp) {
+				change_t38_state(p, T38_DISABLED);
+				if (p->t38.state == T38_PEER_REINVITE) {
+					AST_SCHED_DEL(sched, p->t38id);
+					transmit_response_reliable(p, "488 Not acceptable here", &p->initreq);
+				}
+				break;
+		} else if (p->t38.state == T38_PEER_REINVITE) {
 			AST_SCHED_DEL(sched, p->t38id);
 			p->t38.our_parms = *parameters;
 			/* modify our parameters to conform to the peer's parameters,
@@ -5557,7 +5579,7 @@
 			ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp);
 			change_t38_state(p, T38_ENABLED);
 			transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
-		} else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->t38.state != T38_ENABLED) {
+		} else if (p->t38.state != T38_ENABLED) {
 			p->t38.our_parms = *parameters;
 			ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp);
 			change_t38_state(p, T38_LOCAL_REINVITE);
@@ -6872,10 +6894,10 @@
 	}
 	/* We only want the m and c lines for audio */
 	for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) {
-		if ((media == SDP_AUDIO && ((sscanf(m, "audio %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
-		    (sscanf(m, "audio %30d RTP/AVP %n", &x, &len) == 1 && len > 0))) ||
-			(media == SDP_VIDEO && ((sscanf(m, "video %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
-		    (sscanf(m, "video %30d RTP/AVP %n", &x, &len) == 1 && len > 0)))) {
+		if ((media == SDP_AUDIO && ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+		    (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0))) ||
+			(media == SDP_VIDEO && ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+		    (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len > 0)))) {
 			/* See if there's a c= line for this media stream.
 			 * XXX There is no guarantee that we'll be grabbing the c= line for this
 			 * particular media stream here. However, this is the same logic used in process_sdp.
@@ -7082,8 +7104,8 @@
 		nextm = get_sdp_iterate(&next, req, "m");
 
 		/* Search for audio media definition */
-		if ((sscanf(m, "audio %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
-		    (sscanf(m, "audio %30d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
+		if ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+		    (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) {
 			audio = TRUE;
 			p->offered_media[SDP_AUDIO].offered = TRUE;
 			numberofmediastreams++;
@@ -7093,7 +7115,7 @@
 			codecs = m + len;
 			ast_copy_string(p->offered_media[SDP_AUDIO].text, codecs, sizeof(p->offered_media[SDP_AUDIO].text));
 			for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
-				if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
+				if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
 					ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
 					return -1;
 				}
@@ -7103,8 +7125,8 @@
 				ast_rtp_set_m_type(newaudiortp, codec);
 			}
 		/* Search for video media definition */
-		} else if ((sscanf(m, "video %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
-			   (sscanf(m, "video %30d RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
+		} else if ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+			   (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
 			video = TRUE;
 			p->novideo = FALSE;
 			p->offered_media[SDP_VIDEO].offered = TRUE;
@@ -7115,7 +7137,7 @@
 			codecs = m + len;
 			ast_copy_string(p->offered_media[SDP_VIDEO].text, codecs, sizeof(p->offered_media[SDP_VIDEO].text));
 			for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
-				if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
+				if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
 					ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
 					return -1;
 				}
@@ -7124,8 +7146,8 @@
 				ast_rtp_set_m_type(newvideortp, codec);
 			}
 		/* Search for text media definition */
-		} else if ((sscanf(m, "text %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
-			   (sscanf(m, "text %30d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
+		} else if ((sscanf(m, "text %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+			   (sscanf(m, "text %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) {
 			text = TRUE;
 			p->notext = FALSE;
 			p->offered_media[SDP_TEXT].offered = TRUE;
@@ -7136,7 +7158,7 @@
 			codecs = m + len;
 			ast_copy_string(p->offered_media[SDP_TEXT].text, codecs, sizeof(p->offered_media[SDP_TEXT].text));
 			for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
-				if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
+				if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
 					ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
 					return -1;
 				}
@@ -7145,8 +7167,8 @@
 				ast_rtp_set_m_type(newtextrtp, codec);
 			}
 		/* Search for image media definition */
-		} else if (p->udptl && ((sscanf(m, "image %30d udptl t38%n", &x, &len) == 1 && len > 0) ||
-					(sscanf(m, "image %30d UDPTL t38%n", &x, &len) == 1 && len > 0) )) {
+		} else if (p->udptl && ((sscanf(m, "image %30u udptl t38%n", &x, &len) == 1 && len > 0) ||
+					(sscanf(m, "image %30u UDPTL t38%n", &x, &len) == 1 && len > 0) )) {
 			image = TRUE;
 			if (debug)
 				ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid);
@@ -7378,6 +7400,12 @@
 			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));
 
+			/* 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)) {
+				/* setting to zero will force a default if none was provided by the SDP */
+				ast_udptl_set_far_max_datagram(p->udptl, 0);
+			}
+
 			/* Remote party offers T38, we need to update state */
 			if ((t38action == SDP_T38_ACCEPT) &&
 			    (p->t38.state == T38_LOCAL_REINVITE)) {
@@ -7705,12 +7733,12 @@
 {
 	int found = FALSE;
 	char s[256];
-	int x;
-
-	if ((sscanf(a, "T38FaxMaxBuffer:%30d", &x) == 1)) {
+	unsigned int x;
+
+	if ((sscanf(a, "T38FaxMaxBuffer:%30u", &x) == 1)) {
 		ast_debug(3, "MaxBufferSize:%d\n", x);
 		found = TRUE;
-	} else if ((sscanf(a, "T38MaxBitRate:%30d", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%30d", &x) == 1)) {
+	} else if ((sscanf(a, "T38MaxBitRate:%30u", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%30u", &x) == 1)) {
 		ast_debug(3, "T38MaxBitRate: %d\n", x);
 		switch (x) {
 		case 14400:
@@ -7733,21 +7761,21 @@
 			break;
 		}
 		found = TRUE;
-	} else if ((sscanf(a, "T38FaxVersion:%30d", &x) == 1)) {
-		ast_debug(3, "FaxVersion: %d\n", x);
+	} else if ((sscanf(a, "T38FaxVersion:%30u", &x) == 1)) {
+		ast_debug(3, "FaxVersion: %u\n", x);
 		p->t38.their_parms.version = x;
 		found = TRUE;
-	} else if ((sscanf(a, "T38FaxMaxDatagram:%30d", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30d", &x) == 1)) {
+	} else if ((sscanf(a, "T38FaxMaxDatagram:%30u", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30u", &x) == 1)) {
 		/* override the supplied value if the configuration requests it */
 		if (p->t38_maxdatagram > x) {
 			ast_debug(1, "Overriding T38FaxMaxDatagram '%d' with '%d'\n", x, p->t38_maxdatagram);
 			x = p->t38_maxdatagram;
 		}
-		ast_debug(3, "FaxMaxDatagram: %d\n", x);
+		ast_debug(3, "FaxMaxDatagram: %u\n", x);
 		ast_udptl_set_far_max_datagram(p->udptl, x);
 		found = TRUE;
 	} else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) {
-		if (sscanf(a, "T38FaxFillBitRemoval:%30d", &x) == 1) {
+		if (sscanf(a, "T38FaxFillBitRemoval:%30u", &x) == 1) {
 			ast_debug(3, "FillBitRemoval: %d\n", x);
 			if (x == 1) {
 				p->t38.their_parms.fill_bit_removal = TRUE;
@@ -7758,7 +7786,7 @@
 		}
 		found = TRUE;
 	} else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) {
-		if (sscanf(a, "T38FaxTranscodingMMR:%30d", &x) == 1) {
+		if (sscanf(a, "T38FaxTranscodingMMR:%30u", &x) == 1) {
 			ast_debug(3, "Transcoding MMR: %d\n", x);
 			if (x == 1) {
 				p->t38.their_parms.transcoding_mmr = TRUE;
@@ -7769,7 +7797,7 @@
 		}
 		found = TRUE;
 	} else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) {
-		if (sscanf(a, "T38FaxTranscodingJBIG:%30d", &x) == 1) {
+		if (sscanf(a, "T38FaxTranscodingJBIG:%30u", &x) == 1) {
 			ast_debug(3, "Transcoding JBIG: %d\n", x);
 			if (x == 1) {
 				p->t38.their_parms.transcoding_jbig = TRUE;
@@ -9068,7 +9096,7 @@
 			ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:localTCF\r\n");
 			break;
 		}
-		ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", ast_udptl_get_local_max_datagram(p->udptl));
+		ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%u\r\n", ast_udptl_get_local_max_datagram(p->udptl));
 		switch (ast_udptl_get_error_correction_scheme(p->udptl)) {
 		case UDPTL_ERROR_CORRECTION_NONE:
 			break;
@@ -21017,7 +21045,7 @@
 				ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
 				ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
 			} else if (!strncasecmp(word, "maxdatagram=", 12)) {
-				if (sscanf(&word[12], "%30d", maxdatagram) != 1) {
+				if (sscanf(&word[12], "%30u", maxdatagram) != 1) {
 					ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config);
 					*maxdatagram = global_t38_maxdatagram;
 				}

Modified: tags/1.6.0.22/include/asterisk/udptl.h
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.0.22/include/asterisk/udptl.h?view=diff&rev=244386&r1=244385&r2=244386
==============================================================================
--- tags/1.6.0.22/include/asterisk/udptl.h (original)
+++ tags/1.6.0.22/include/asterisk/udptl.h Tue Feb  2 13:57:47 2010
@@ -108,12 +108,28 @@
 
 void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp);
 
+/*! 
+ * \brief retrieves local_max_datagram.
+ * 
+ * \retval positive value representing max datagram size.
+ * \retval 0 if no value is present
+ */
 unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl);
 
+/*! 
+ * \brief sets far max datagram size.  If max_datagram is = 0, the far max datagram
+ *  size is set to a default value.
+ */
 void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram);
 
 unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl);
 
+/*! 
+ * \brief retrieves far max ifp
+ * 
+ * \retval positive value representing max ifp size
+ * \retval 0 if no value is present
+ */
 unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl);
 
 void ast_udptl_setnat(struct ast_udptl *udptl, int nat);

Modified: tags/1.6.0.22/main/udptl.c
URL: http://svnview.digium.com/svn/asterisk/tags/1.6.0.22/main/udptl.c?view=diff&rev=244386&r1=244385&r2=244386
==============================================================================
--- tags/1.6.0.22/main/udptl.c (original)
+++ tags/1.6.0.22/main/udptl.c Tue Feb  2 13:57:47 2010
@@ -91,6 +91,8 @@
 static int use_even_ports;
 
 #define LOCAL_FAX_MAX_DATAGRAM      1400
+#define DEFAULT_FAX_MAX_DATAGRAM    400
+#define FAX_MAX_DATAGRAM_LIMIT      1400
 #define MAX_FEC_ENTRIES             5
 #define MAX_FEC_SPAN                5
 
@@ -854,9 +856,13 @@
 
 void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
 {
-	udptl->local_max_ifp = max_ifp;
-	/* reset calculated values so they'll be computed again */
-	udptl->local_max_datagram = -1;
+	/* make sure max_ifp is a positive value since a cast will take place when
+	 * when setting local_max_ifp */
+	if ((signed int) max_ifp > 0) {
+		udptl->local_max_ifp = max_ifp;
+		/* reset calculated values so they'll be computed again */
+		udptl->local_max_datagram = -1;
+	}
 }
 
 unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
@@ -864,18 +870,30 @@
 	if (udptl->local_max_datagram == -1) {
 		calculate_local_max_datagram(udptl);
 	}
+
+	/* this function expects a unsigned value in return. */
+	if (udptl->local_max_datagram < 0) {
+		return 0;
+	}
 	return udptl->local_max_datagram;
 }
 
 void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram)
 {
-	udptl->far_max_datagram = max_datagram;
+	if (!max_datagram || (max_datagram > FAX_MAX_DATAGRAM_LIMIT)) {
+		udptl->far_max_datagram = DEFAULT_FAX_MAX_DATAGRAM;
+	} else {
+		udptl->far_max_datagram = max_datagram;
+	}
 	/* reset calculated values so they'll be computed again */
 	udptl->far_max_ifp = -1;
 }
 
 unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl)
 {
+	if (udptl->far_max_datagram < 0) {
+		return 0;
+	}
 	return udptl->far_max_datagram;
 }
 
@@ -883,6 +901,10 @@
 {
 	if (udptl->far_max_ifp == -1) {
 		calculate_far_max_ifp(udptl);
+	}
+
+	if (udptl->far_max_ifp < 0) {
+		return 0;
 	}
 	return udptl->far_max_ifp;
 }
@@ -1033,7 +1055,11 @@
 	unsigned int seq;
 	unsigned int len = f->datalen;
 	int res;
-	uint8_t buf[s->far_max_datagram];
+	/* if no max datagram size is provided, use default value */
+	const int bufsize = (s->far_max_datagram > 0) ? s->far_max_datagram : DEFAULT_FAX_MAX_DATAGRAM;
+	uint8_t buf[bufsize];
+
+	memset(buf, 0, sizeof(buf));
 
 	/* If we have no peer, return immediately */	
 	if (s->them.sin_addr.s_addr == INADDR_ANY)




More information about the asterisk-commits mailing list