aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/util-buffer.h
blob: 58d5098a2820cb86987c51c8b45df56dd3357b1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/* 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>
 */

#ifndef __UTIL_BUFFER_H__
#define __UTIL_BUFFER_H__

typedef struct MemBuffer_ {
   uint8_t *buffer;
   uint32_t size;
   uint32_t offset;
} MemBuffer;

MemBuffer *MemBufferCreateNew(uint32_t size);
int MemBufferExpand(MemBuffer **buffer, uint32_t expand_by);
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 Get the MemBuffers underlying buffer.
 */
#define MEMBUFFER_BUFFER(mem_buffer) (mem_buffer)->buffer

/**
 * \brief Get the MemBuffers current offset.
 */
#define MEMBUFFER_OFFSET(mem_buffer) (mem_buffer)->offset

/**
 * \brief Get the MemBuffers current size.
 */
#define MEMBUFFER_SIZE(mem_buffer) (mem_buffer)->size

/**
 * \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) ({                           \
    fwrite((mem_buffer)->buffer, sizeof(uint8_t), (mem_buffer)->offset, fp);    \
})

/**
 * \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 " \
                       "- %"PRIu32"\n", (dst)->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';                                \
    } 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) {                 \
                SCLogDebug("Truncating data write since it exceeded buffer " \
                           "limit of - %"PRIu32"\n", (dst)->size); \
                (dst)->offset = (dst)->size - 1;                        \
            } else {                                                    \
                (dst->offset) += cw;                                    \
            }                                                           \
        }                                                               \
    } while (0)

#endif /* __UTIL_BUFFER_H__ */