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 <[email protected]>
Committer: Daniel-Constantin Mierla <[email protected]>
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)) {


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to