[sr-dev] git:3.2: core/tcp: clone received message over tcp in local buffer

Daniel-Constantin Mierla miconda at gmail.com
Sun Dec 11 23:17:55 CET 2011


Module: sip-router
Branch: 3.2
Commit: 9180356a88313a1026238fabb693efed92227600
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=9180356a88313a1026238fabb693efed92227600

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date:   Fri Dec  2 13:05:55 2011 +0100

core/tcp: clone received message over tcp in local buffer

- receive_msg() got pointer inside tcp stream as rcv buffer, linking it to
  msg->buf, but there are places where the content of msg->buf is
  changed (topoh, msg_apply_changes) which can result in corruption of
  tcp stream content
- added a wrapper function receive_tcp_msg() to clone the content and
  have same behaviour as for udp or sctp
- reported by Hugh Waite, FS#185
(cherry picked from commit 6ebd0a6bf1cbacf73f45ff42d368f22304bff11b)

---

 tcp_read.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/tcp_read.c b/tcp_read.c
index 1ba6cbb..c180301 100644
--- a/tcp_read.c
+++ b/tcp_read.c
@@ -848,6 +848,62 @@ skip:
 }
 
 
+/**
+ * @brief wrapper around receive_msg() to clone the tcpbuf content
+ *
+ * When receiving over TCP, tcpbuf points inside the TCP stream buffer, but during
+ * processing of config, msg->buf content might be changed and may corrupt
+ * the content of the stream. Safer, make a clone of buf content in a local
+ * buffer and give that to receive_msg() to link to msg->buf
+ */
+int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_info)
+{
+#ifdef DYN_BUF
+	char *buf = NULL;
+#else
+	static char *buf = NULL;
+	static unsigned int bsize = 0;
+#endif
+	int blen;
+
+	/* min buffer size is BUF_SIZE */
+	blen = len;
+	if(blen < BUF_SIZE)
+		blen = BUF_SIZE;
+
+#ifdef DYN_BUF
+	buf=pkg_malloc(blen+1);
+	if (buf==0) {
+		LM_ERR("could not allocate receive buffer\n");
+		return -1;
+	}
+#else
+	/* allocate buffer when needed
+	 * - no buffer yet
+	 * - existing buffer too small (min size is BUF_SIZE - to accomodate most
+	 *   of SIP messages; expected larger for HTTP/XCAP)
+	 * - existing buffer too large (e.g., we got a too big message in the past,
+	 *   let's free it)
+	 *
+	 * - also, use system memory, not to eat from PKG (same as static buffer
+	 *   from PKG pov)
+	 */
+	if(buf==NULL || bsize < blen || blen < bsize/2) {
+		if(buf!=NULL)
+			free(buf);
+		buf=malloc(blen+1);
+		if (buf==0) {
+			LM_ERR("could not allocate receive buffer\n");
+			return -1;
+		}
+		bsize = blen;
+	}
+#endif
+
+	memcpy(buf, tcpbuf, len);
+	buf[len] = '\0';
+	return receive_msg(buf, len, rcv_info);
+}
 
 int tcp_read_req(struct tcp_connection* con, int* bytes_read, int* read_flags)
 {
@@ -932,7 +988,7 @@ again:
 			/* if we are here everything is nice and ok*/
 			resp=CONN_RELEASE;
 #ifdef EXTRA_DEBUG
-			DBG("calling receive_msg(%p, %d, )\n",
+			DBG("receiving msg(%p, %d, )\n",
 					req->start, (int)(req->parsed-req->start));
 #endif
 			/* rcv.bind_address should always be !=0 */
@@ -970,12 +1026,12 @@ again:
 			if (unlikely(req->state==H_HTTP11_CHUNK_FINISH)){
 				/* http chunked request */
 				req->body[req->content_len] = 0;
-				ret = receive_msg(req->start,
+				ret = receive_tcp_msg(req->start,
 						req->body + req->content_len - req->start,
 						&con->rcv);
 			}else
 #endif
-				ret = receive_msg(req->start, req->parsed-req->start,
+				ret = receive_tcp_msg(req->start, req->parsed-req->start,
 									&con->rcv);
 				
 			if (unlikely(ret < 0)) {




More information about the sr-dev mailing list