Module: sip-router
Branch: master
Commit: 6ebd0a6bf1cbacf73f45ff42d368f22304bff11b
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6ebd0a6…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)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
---
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)) {