]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Introduce new buffer API that lets you create and manage a buffer. Update http log...
authorAnoop Saldanha <poonaatsoc@gmail.com>
Thu, 5 Apr 2012 03:28:19 +0000 (08:58 +0530)
committerVictor Julien <victor@inliniac.net>
Tue, 10 Apr 2012 15:57:58 +0000 (17:57 +0200)
src/Makefile.am
src/log-httplog.c
src/util-buffer.c [new file with mode: 0644]
src/util-buffer.h [new file with mode: 0644]
src/util-error.c
src/util-error.h

index e5af8c38f40a0f9bcee12f511f51ad502a1717d2..20e600000698d7af1ec9e098dc4b882c0e813ca7 100644 (file)
@@ -239,6 +239,7 @@ util-checksum.c util-checksum.h \
 util-runmodes.c util-runmodes.h \
 util-file.c util-file.h \
 util-path.c util-path.h \
+util-buffer.c util-buffer.h \
 tm-modules.c tm-modules.h \
 tm-queues.c tm-queues.h \
 tm-queuehandlers.c tm-queuehandlers.h \
index 0d4baa56ea03a06e1cfbf09f40889de2f904b4b8..a0911c37dc134b869445b1048196f6b859cd11df 100644 (file)
@@ -45,6 +45,7 @@
 #include "app-layer-htp.h"
 #include "app-layer.h"
 #include "util-privs.h"
+#include "util-buffer.h"
 
 #include "util-logopenfile.h"
 
@@ -108,8 +109,7 @@ typedef struct LogHttpLogThread_ {
     /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
     uint32_t uri_cnt;
 
-    char *data;
-    uint32_t data_offset;
+    MemBuffer *buffer;
 } LogHttpLogThread;
 
 static void CreateTimeString (const struct timeval *ts, char *str, size_t size) {
@@ -124,7 +124,7 @@ static void CreateTimeString (const struct timeval *ts, char *str, size_t size)
 
 static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
 {
-    PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, " [**] ");
+    MemBufferWriteString(aft->buffer, " [**] ");
 
     /* referer */
     htp_header_t *h_referer = NULL;
@@ -132,56 +132,54 @@ static void LogHttpLogExtended(LogHttpLogThread *aft, htp_tx_t *tx)
         h_referer = table_getc(tx->request_headers, "referer");
     }
     if (h_referer != NULL) {
-        PrintRawUriBuf(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
+        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                        (uint8_t *)bstr_ptr(h_referer->value),
                        bstr_len(h_referer->value));
     } else {
-        PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, "<no referer>");
+        MemBufferWriteString(aft->buffer, "<no referer>");
     }
-    PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, " [**] ");
+    MemBufferWriteString(aft->buffer, " [**] ");
 
     /* method */
     if (tx->request_method != NULL) {
-        PrintRawUriBuf(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
+        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                        (uint8_t *)bstr_ptr(tx->request_method),
                        bstr_len(tx->request_method));
     }
-    PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, " [**] ");
+    MemBufferWriteString(aft->buffer, " [**] ");
 
     /* protocol */
     if (tx->request_protocol != NULL) {
-        PrintRawUriBuf(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
+        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                        (uint8_t *)bstr_ptr(tx->request_protocol),
                        bstr_len(tx->request_protocol));
     } else {
-        PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, "<no protocol>");
+        MemBufferWriteString(aft->buffer, "<no protocol>");
     }
-    PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, " [**] ");
+    MemBufferWriteString(aft->buffer, " [**] ");
 
     /* response status */
     if (tx->response_status != NULL) {
-        PrintRawUriBuf(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
+        PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                        (uint8_t *)bstr_ptr(tx->response_status),
                        bstr_len(tx->response_status));
-
         /* Redirect? */
         if ((tx->response_status_number > 300) && ((tx->response_status_number) < 303)) {
             htp_header_t *h_location = table_getc(tx->response_headers, "location");
             if (h_location != NULL) {
-                PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, " => ");
+                MemBufferWriteString(aft->buffer, " => ");
 
-                PrintRawUriBuf(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
+                PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                                (uint8_t *)bstr_ptr(h_location->value),
                                bstr_len(h_location->value));
             }
         }
     } else {
-        PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, "<no status>");
+        MemBufferWriteString(aft->buffer, "<no status>");
     }
 
     /* length */
-    PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
-                    " [**] %"PRIuMAX" bytes", (uintmax_t)tx->response_message_len);
+    MemBufferWriteString(aft->buffer, " [**] %"PRIuMAX" bytes", (uintmax_t)tx->response_message_len);
 }
 
 static TmEcode LogHttpLogIPWrapper(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq,
@@ -280,33 +278,30 @@ static TmEcode LogHttpLogIPWrapper(ThreadVars *tv, Packet *p, void *data, Packet
         SCLogDebug("got a HTTP request and now logging !!");
 
         /* reset */
-        aft->data[0] = '\0';
-        aft->data_offset = 0;
+        MemBufferReset(aft->buffer);
 
         /* time */
-        PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
-                         "%s ", timebuf);
+        MemBufferWriteString(aft->buffer, "%s", timebuf);
 
         /* hostname */
         if (tx->parsed_uri != NULL &&
                 tx->parsed_uri->hostname != NULL)
         {
-            PrintRawUriBuf(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
+            PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                            (uint8_t *)bstr_ptr(tx->parsed_uri->hostname),
                            bstr_len(tx->parsed_uri->hostname));
         } else {
-            PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
-                            "<hostname unknown>");
+            MemBufferWriteString(aft->buffer, "<hostname unknown>");
         }
-        PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, " [**] ");
+        MemBufferWriteString(aft->buffer, " [**] ");
 
         /* uri */
         if (tx->request_uri != NULL) {
-            PrintRawUriBuf(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
+            PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                            (uint8_t *)bstr_ptr(tx->request_uri),
                            bstr_len(tx->request_uri));
         }
-        PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE, " [**] ");
+        MemBufferWriteString(aft->buffer, " [**] ");
 
         /* user agent */
         htp_header_t *h_user_agent = NULL;
@@ -314,27 +309,25 @@ static TmEcode LogHttpLogIPWrapper(ThreadVars *tv, Packet *p, void *data, Packet
             h_user_agent = table_getc(tx->request_headers, "user-agent");
         }
         if (h_user_agent != NULL) {
-            PrintRawUriBuf(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
+            PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                             (uint8_t *)bstr_ptr(h_user_agent->value),
                             bstr_len(h_user_agent->value));
         } else {
-            PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
-                            "<useragent unknown>");
+            MemBufferWriteString(aft->buffer, "<useragent unknown>");
         }
         if (hlog->flags & LOG_HTTP_EXTENDED) {
             LogHttpLogExtended(aft, tx);
         }
 
         /* ip/tcp header info */
-        PrintBufferData(aft->data, &aft->data_offset, OUTPUT_BUFFER_SIZE,
-                        " [**] %s:%" PRIu16 " -> %s:%" PRIu16 "\n",
-                        srcip, sp, dstip, dp);
-
+        MemBufferWriteString(aft->buffer,
+                             " [**] %s:%" PRIu16 " -> %s:%" PRIu16 "\n",
+                             srcip, sp, dstip, dp);
 
         aft->uri_cnt ++;
 
         SCMutexLock(&hlog->file_ctx->fp_mutex);
-        fprintf(hlog->file_ctx->fp, "%s", aft->data);
+        MemBufferPrintToFPAsString(aft->buffer, hlog->file_ctx->fp);
         fflush(hlog->file_ctx->fp);
         SCMutexUnlock(&hlog->file_ctx->fp_mutex);
 
@@ -393,12 +386,10 @@ TmEcode LogHttpLogThreadInit(ThreadVars *t, void *initdata, void **data)
         return TM_ECODE_FAILED;
     }
 
-    aft->data = SCMalloc(OUTPUT_BUFFER_SIZE);
-    if (aft->data == NULL) {
+    aft->buffer = MemBufferCreateNew(OUTPUT_BUFFER_SIZE);
+    if (aft->buffer == NULL) {
         return TM_ECODE_FAILED;
     }
-    aft->data[0] = '\0';
-    aft->data_offset = 0;
 
     /* Use the Ouptut Context (file pointer and mutex) */
     aft->httplog_ctx= ((OutputCtx *)initdata)->data;
@@ -416,6 +407,7 @@ TmEcode LogHttpLogThreadDeinit(ThreadVars *t, void *data)
 
     /* clear memory */
     memset(aft, 0, sizeof(LogHttpLogThread));
+    MemBufferFree(aft->buffer);
 
     SCFree(aft);
     return TM_ECODE_OK;
diff --git a/src/util-buffer.c b/src/util-buffer.c
new file mode 100644 (file)
index 0000000..903b58e
--- /dev/null
@@ -0,0 +1,60 @@
+/* Copyright (C) 2007-2012 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ */
+
+#include "suricata-common.h"
+#include "suricata.h"
+#include "util-debug.h"
+#include "util-buffer.h"
+
+/* 10 mb */
+#define MAX_LIMIT 10485760
+
+MemBuffer *MemBufferCreateNew(uint32_t size)
+{
+    if (size > MAX_LIMIT) {
+        SCLogWarning(SC_ERR_MEM_BUFFER_API, "Mem buffer asked to create "
+                     "buffer with size greater than API limit - %d\n",
+                     MAX_LIMIT);
+        return NULL;
+    }
+
+    uint32_t total_size = size + sizeof(MemBuffer);
+
+    MemBuffer *buffer = SCMalloc(total_size);
+    if (buffer == NULL) {
+        return NULL;
+    }
+    memset(buffer, 0, total_size);
+
+    buffer->size = size;
+    buffer->buffer = (uint8_t *)buffer + sizeof(MemBuffer);
+
+    return buffer;
+}
+
+void MemBufferFree(MemBuffer *buffer)
+{
+    SCFree(buffer);
+
+    return;
+}
diff --git a/src/util-buffer.h b/src/util-buffer.h
new file mode 100644 (file)
index 0000000..162a2a4
--- /dev/null
@@ -0,0 +1,156 @@
+/* Copyright (C) 2007-2012 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ */
+
+typedef struct MemBuffer_ {
+   uint8_t *buffer;
+   uint32_t size;
+   uint32_t offset;
+} MemBuffer;
+
+MemBuffer *MemBufferCreateNew(uint32_t size);
+void MemBufferFree(MemBuffer *buffer);
+
+/**
+ * \brief Reset the mem buffer.
+ *
+ * \param mem_buffer Pointer to the mem buffer instance.
+ */
+#define MemBufferReset(mem_buffer) do {                     \
+        (mem_buffer)->buffer[0] = 0;                        \
+        (mem_buffer)->offset = 0;                           \
+    } while (0)
+
+/**
+ * \brief Write a buffer to the file pointer.
+ *
+ *        Accepted buffers can contain both printable and non-printable
+ *        characters.  Printable characters are written in the printable
+ *        format and the non-printable chars are written in hex codes
+ *        using the |XX| format.
+ *
+ *        For example this would be the kind of output in the file -
+ *        onetwo|EF|three|ED|five
+ *
+ * \param buffer Pointer to the src MemBuffer instance to write.
+ * \param fp     Pointer to the file file instance to write to.
+ */
+#define MemBufferPrintToFP(buffer, fp) do {             \
+        uint32_t i;                                     \
+                                                        \
+        for (i = 0; i < (buffer)->offset; i++) {            \
+            if (isprint(buffer->buffer[i]))                 \
+                fprintf(fp, "%c", (buffer)->buffer[i]);     \
+            else                                            \
+                fprintf(fp, "|%02X|", (buffer)->buffer[i]); \
+        }                                                   \
+    } while (0)
+
+/**
+ * \brief Write a buffer to the file pointer as a printable char string.
+ *
+ * \param buffer Pointer to the src MemBuffer instance to write.
+ * \param fp     Pointer to the file file instance to write to.
+ */
+#define MemBufferPrintToFPAsString(mem_buffer, fp) do {                     \
+        fwrite((mem_buffer)->buffer, sizeof(uint8_t), (mem_buffer)->offset, fp); \
+    } while (0)
+
+/**
+ * \brief Write a buffer in hex format.
+ *
+ * \param buffer Pointer to the src MemBuffer instance to write.
+ * \param fp     Pointer to the file file instance to write to.
+ */
+#define MemBufferPrintToFPAsHex(buffer, fp) do {        \
+        uint32_t i;                                     \
+                                                        \
+        for (i = 0; i < (buffer)->offset; i++) {        \
+            if (((buffer)->offset % 8) == 0)            \
+                fprintf(fp, "\n");                      \
+            fprintf(fp, " %02X", (buffer)->buffer[i]);  \
+        }                                               \
+    } while (0)
+
+
+/**
+ * \brief Write a raw buffer to the MemBuffer dst.
+ *
+ *        When we say raw buffer it indicates a buffer that need not be
+ *        purely a string buffer.  It can be a pure string buffer or not or
+ *        a mixture of both.  Hence we don't accept any format strings.
+ *
+ *        If the remaining space on the buffer is lesser than the length of
+ *        the buffer to write, it is truncated to fit into the empty space.
+ *
+ *        Also after every write a '\0' is appended.  This would indicate
+ *        that the total available space to write in the buffer is
+ *        MemBuffer->size - 1 and not Membuffer->size.  The reason we
+ *        append the '\0' is for supporting writing pure string buffers
+ *        as well, that can later be used by other string handling funcs.
+ *
+ * \param raw_buffer     The buffer to write.
+ * \param raw_buffer_len Length of the above buffer.
+ */
+#define MemBufferWriteRaw(dst, raw_buffer, raw_buffer_len) do { \
+        uint32_t write_len;                                     \
+                                                                \
+        if (((raw_buffer_len) >= (dst)->size - (dst)->offset)) {        \
+            SCLogDebug("Truncating data write since it exceeded buffer limit of " \
+                       "- %d\n", buffer->size);                         \
+            write_len = ((dst)->size - (dst)->offset) - 1;              \
+        } else {                                                        \
+            write_len = (raw_buffer_len);                               \
+        }                                                               \
+                                                                        \
+        memcpy((dst)->buffer + (dst)->offset, (raw_buffer), write_len); \
+        (dst)->offset += write_len;                                     \
+        dst->buffer[dst->offset] = '\0';                                \
+                                                                        \
+        return;                                                         \
+    } while (0)
+
+/**
+ * \brief Write a string buffer to the Membuffer dst.
+ *
+ *        This function takes a format string and arguments for the format
+ *        string like sprintf.
+ *
+ *        An example usage of this is -
+ *        MemBufferWriteString(mem_buffer_instance, \"%d - %s\", 10, \"one\");
+ *
+ * \param dst    The dst MemBuffer instance.
+ * \param format The format string.
+ * \param ...    Variable arguments.
+ */
+#define MemBufferWriteString(dst, ...) do {                             \
+        int cw = snprintf((char *)(dst)->buffer + (dst)->offset,        \
+                          (dst)->size - (dst)->offset,                  \
+                          __VA_ARGS__);                                 \
+        if (cw >= 0) {                                                  \
+            if ( ((dst)->offset + cw) >= (dst)->size) {                 \
+                (dst)->offset = (dst)->size - 1;                        \
+            } else {                                                    \
+                (dst->offset) += cw;                                    \
+            }                                                           \
+        }                                                               \
+    } while (0)
index e39131cc0404f2ceea6bf33258af60595a080432..0ca3d41dea91de248368bd89a107780527823e46 100644 (file)
@@ -225,6 +225,7 @@ const char * SCErrorToString(SCError err)
         CASE_CODE (SC_WARN_PROFILE);
         CASE_CODE (SC_ERR_FLOW_INIT);
         CASE_CODE (SC_ERR_HOST_INIT);
+        CASE_CODE (SC_ERR_MEM_BUFFER_API);
 
         default:
             return "UNKNOWN_ERROR";
index 1bd80a709688bce3a7b9d0d758a5610d57f11ac1..52fa0c1658488aaff3a743e3c7ffce41daf7c387 100644 (file)
@@ -240,6 +240,7 @@ typedef enum {
     SC_WARN_PROFILE,
     SC_ERR_FLOW_INIT,
     SC_ERR_HOST_INIT,
+    SC_ERR_MEM_BUFFER_API,
 } SCError;
 
 const char *SCErrorToString(SCError);