#include "app-layer-htp.h"
#include "app-layer.h"
#include "util-privs.h"
+#include "util-buffer.h"
#include "util-logopenfile.h"
/** 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) {
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;
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,
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;
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);
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;
/* clear memory */
memset(aft, 0, sizeof(LogHttpLogThread));
+ MemBufferFree(aft->buffer);
SCFree(aft);
return TM_ECODE_OK;
--- /dev/null
+/* 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)