suricata
log-cf-common.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2016 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Paulo Pacheco <fooinha@gmail.com>
22 * \author Victor Julien <victor@inliniac.net>
23 * \author Ignacio Sanchez <sanchezmartin.ji@gmail.com>
24 *
25 * Common custom logging format
26 */
27
28#include "log-cf-common.h"
29#include "util-print.h"
30#include "util-unittest.h"
31#include "util-time.h"
32#include "util-debug.h"
33
34/**
35 * \brief Creates a custom format node
36 * \retval LogCustomFormatNode * ptr if created
37 * \retval NULL if failed to allocate
38 */
40{
42 if (unlikely(node == NULL)) {
43 SCLogError("Failed to alloc custom format node");
44 return NULL;
45 }
46 return node;
47}
48
49/**
50 * \brief Creates a custom format.
51 * \retval LogCustomFormat * ptr if created
52 * \retval NULL if failed to allocate
53 */
55{
56 LogCustomFormat * cf = SCCalloc(1, sizeof(LogCustomFormat));
57 if (unlikely(cf == NULL)) {
58 SCLogError("Failed to alloc custom format");
59 return NULL;
60 }
61 return cf;
62}
63
64/**
65 * \brief Frees memory held by a custom format node
66 * \param LogCustomFormatNode * node - node to release
67 */
69{
70 if (node==NULL)
71 return;
72
73 SCFree(node);
74}
75
76/**
77 * \brief Frees memory held by a custom format
78 * \param LogCustomFormat * cf - format to release
79 */
81{
82 if (cf==NULL)
83 return;
84
85 for (size_t i = 0; i < cf->cf_n; ++i) {
87 }
88 SCFree(cf);
89}
90
91/**
92 * \brief Parses and saves format nodes for custom format
93 * \param LogCustomFormat * cf - custom format to build
94 * \param const char * format - string with format specification
95 */
96int LogCustomFormatParse(LogCustomFormat *cf, const char *format)
97{
98 const char *p, *np;
99 uint32_t n;
100 LogCustomFormatNode *node = NULL;
101
102 if (cf==NULL)
103 return 0;
104
105 if (format==NULL)
106 return 0;
107
108 p=format;
109
110 for (cf->cf_n = 0; cf->cf_n < LOG_MAXN_NODES-1 && p && *p != '\0';){
111
113 if (node == NULL) {
114 goto parsererror;
115 }
116 node->maxlen = 0;
117
118 if (*p != '%'){
119 /* Literal found in format string */
120 node->type = LOG_CF_LITERAL;
121 np = strchr(p, '%');
122 if (np == NULL){
123 n = LOG_NODE_STRLEN-2;
124 np = NULL; /* End */
125 }else{
126 n = (uint32_t)(np - p);
127 }
128 strlcpy(node->data,p,n+1);
129 p = np;
130 } else {
131 /* Non Literal found in format string */
132 p++;
133 if (*p == '[') { /* Check if maxlength has been specified (ie: [25]) */
134 p++;
135 np = strchr(p, ']');
136 if (np != NULL) {
137 if (np-p > 0 && np-p < 10){
138 long maxlen = strtol(p,NULL,10);
139 if (maxlen > 0 && maxlen < LOG_NODE_MAXOUTPUTLEN) {
140 node->maxlen = (uint32_t) maxlen;
141 }
142 } else {
143 goto parsererror;
144 }
145 p = np + 1;
146 } else {
147 goto parsererror;
148 }
149 }
150 if (*p == '{') { /* Simple format char */
151 np = strchr(p, '}');
152 if (np != NULL && np-p > 1 && np-p < LOG_NODE_STRLEN-2) {
153 p++;
154 n = (uint32_t)(np - p);
155 strlcpy(node->data, p, n+1);
156 p = np;
157 } else {
158 goto parsererror;
159 }
160 p++;
161 } else {
162 node->data[0] = '\0';
163 }
164 node->type = *p;
165 if (*p == '%'){
166 node->type = LOG_CF_LITERAL;
167 strlcpy(node->data, "%", 2);
168 }
169 p++;
170 }
171 LogCustomFormatAddNode(cf, node);
172 }
173 return 1;
174
175parsererror:
177 return 0;
178}
179
180/**
181 * \brief Adds a node to custom format
182 * \param LogCustomFormat * cf - custom format
183 * \param LogCustomFormatNode * node - node to add
184 */
186{
187 if (cf == NULL || node == NULL)
188 return;
189
190 if (cf->cf_n == LOG_MAXN_NODES) {
191 SCLogWarning("Too many options for custom format");
192 return;
193 }
194
195#ifdef DEBUG
196 SCLogDebug("%d-> n.type=[%d] n.maxlen=[%d] n.data=[%s]",
197 cf->cf_n, node->type, node->maxlen, node->data);
198#endif
199
200 cf->cf_nodes[cf->cf_n] = node;
201 cf->cf_n++;
202}
203
204/**
205 * \brief Writes a timestamp with given format into a MemBuffer
206 * \param MemBuffer * buffer - where to write
207 * \param const char * fmt - format to be used write timestamp
208 * \param const struct timeveal *ts - the timestamp
209 *
210 */
211void LogCustomFormatWriteTimestamp(MemBuffer *buffer, const char *fmt, const SCTime_t ts)
212{
213
214 time_t time = SCTIME_SECS(ts);
215 struct tm local_tm;
216 struct tm *timestamp = SCLocalTime(time, &local_tm);
217 char buf[128] = {0};
218 const char * fmt_to_use = TIMESTAMP_DEFAULT_FORMAT;
219
220 if (fmt && *fmt != '\0') {
221 fmt_to_use = fmt;
222 }
223
224 CreateFormattedTimeString (timestamp, fmt_to_use, buf, sizeof(buf));
225 PrintRawUriBuf((char *)buffer->buffer, &buffer->offset,
226 buffer->size, (uint8_t *)buf,strlen(buf));
227}
228
229#ifdef UNITTESTS
230/**
231 * \internal
232 * \brief This test tests default timestamp format
233 */
234static int LogCustomFormatTest01(void)
235{
236 struct tm tm;
237 tm.tm_sec = 0;
238 tm.tm_min = 30;
239 tm.tm_hour = 4;
240 tm.tm_mday = 13;
241 tm.tm_mon = 0;
242 tm.tm_year = 114;
243 tm.tm_wday = 1;
244 tm.tm_yday = 13;
245 tm.tm_isdst = 0;
246 SCTime_t ts = SCTIME_FROM_SECS(mktime(&tm));
247
248 MemBuffer *buffer = MemBufferCreateNew(62);
249 if (!buffer) {
250 return 0;
251 }
252
254 /*
255 * {buffer = "01/13/14-04:30:00", size = 62, offset = 17}
256 */
257 FAIL_IF_NOT( buffer->offset == 17);
258 FAIL_IF(strcmp((char *)buffer->buffer, "01/13/14-04:30:00") != 0);
259
260 MemBufferFree(buffer);
261
262 return 1;
263}
264
265static void LogCustomFormatRegisterTests(void)
266{
267 UtRegisterTest("LogCustomFormatTest01", LogCustomFormatTest01);
268}
269#endif /* UNITTESTS */
270
272{
273#ifdef UNITTESTS
274 LogCustomFormatRegisterTests();
275#endif /* UNITTESTS */
276}
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
void LogCustomFormatRegister(void)
void LogCustomFormatWriteTimestamp(MemBuffer *buffer, const char *fmt, const SCTime_t ts)
Writes a timestamp with given format into a MemBuffer.
void LogCustomFormatNodeFree(LogCustomFormatNode *node)
Frees memory held by a custom format node.
void LogCustomFormatFree(LogCustomFormat *cf)
Frees memory held by a custom format.
LogCustomFormatNode * LogCustomFormatNodeAlloc(void)
Creates a custom format node.
void LogCustomFormatAddNode(LogCustomFormat *cf, LogCustomFormatNode *node)
Adds a node to custom format.
LogCustomFormat * LogCustomFormatAlloc(void)
Creates a custom format.
int LogCustomFormatParse(LogCustomFormat *cf, const char *format)
Parses and saves format nodes for custom format.
#define LOG_CF_LITERAL
#define TIMESTAMP_DEFAULT_FORMAT
#define LOG_NODE_STRLEN
#define LOG_MAXN_NODES
#define LOG_NODE_MAXOUTPUTLEN
uint64_t ts
char data[LOG_NODE_STRLEN]
LogCustomFormatNode * cf_nodes[LOG_MAXN_NODES]
uint8_t buffer[]
Definition util-buffer.h:30
uint32_t size
Definition util-buffer.h:28
uint32_t offset
Definition util-buffer.h:29
size_t strlcpy(char *dst, const char *src, size_t siz)
MemBuffer * MemBufferCreateNew(uint32_t size)
Definition util-buffer.c:32
void MemBufferFree(MemBuffer *buffer)
Definition util-buffer.c:86
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
void PrintRawUriBuf(char *retbuf, uint32_t *offset, uint32_t retbuflen, const uint8_t *buf, size_t buflen)
Definition util-print.c:93
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition util-time.c:267
void CreateFormattedTimeString(const struct tm *t, const char *fmt, char *str, size_t size)
Definition util-time.c:246
#define SCTIME_FROM_SECS(s)
Definition util-time.h:69
#define SCTIME_SECS(t)
Definition util-time.h:57