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  */
96 int 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 
112  node = LogCustomFormatNodeAlloc();
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 
175 parsererror:
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  */
211 void 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  */
234 static 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 
253  LogCustomFormatWriteTimestamp(buffer, "", ts);
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 
265 static void LogCustomFormatRegisterTests(void)
266 {
267  UtRegisterTest("LogCustomFormatTest01", LogCustomFormatTest01);
268 }
269 #endif /* UNITTESTS */
270 
272 {
273 #ifdef UNITTESTS
274  LogCustomFormatRegisterTests();
275 #endif /* UNITTESTS */
276 }
LogCustomFormatFree
void LogCustomFormatFree(LogCustomFormat *cf)
Frees memory held by a custom format.
Definition: log-cf-common.c:80
ts
uint64_t ts
Definition: source-erf-file.c:55
MemBuffer_::buffer
uint8_t buffer[]
Definition: util-buffer.h:30
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
CreateFormattedTimeString
void CreateFormattedTimeString(const struct tm *t, const char *fmt, char *str, size_t size)
Definition: util-time.c:246
LOG_CF_LITERAL
#define LOG_CF_LITERAL
Definition: log-cf-common.h:39
LogCustomFormatRegister
void LogCustomFormatRegister(void)
Definition: log-cf-common.c:271
LogCustomFormatWriteTimestamp
void LogCustomFormatWriteTimestamp(MemBuffer *buffer, const char *fmt, const SCTime_t ts)
Writes a timestamp with given format into a MemBuffer.
Definition: log-cf-common.c:211
util-unittest.h
MemBuffer_::offset
uint32_t offset
Definition: util-buffer.h:29
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
LOG_MAXN_NODES
#define LOG_MAXN_NODES
Definition: log-cf-common.h:31
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
LogCustomFormat_::cf_n
uint32_t cf_n
Definition: log-cf-common.h:72
LogCustomFormatNode_
Definition: log-cf-common.h:64
LogCustomFormatNode_::type
uint32_t type
Definition: log-cf-common.h:65
SCTIME_FROM_SECS
#define SCTIME_FROM_SECS(s)
Definition: util-time.h:69
util-debug.h
LOG_NODE_STRLEN
#define LOG_NODE_STRLEN
Definition: log-cf-common.h:32
util-print.h
util-time.h
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
SCLocalTime
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition: util-time.c:267
SCTime_t
Definition: util-time.h:40
LogCustomFormatNode_::maxlen
uint32_t maxlen
Definition: log-cf-common.h:66
MemBuffer_
Definition: util-buffer.h:27
LogCustomFormat_
Definition: log-cf-common.h:71
PrintRawUriBuf
void PrintRawUriBuf(char *retbuf, uint32_t *offset, uint32_t retbuflen, uint8_t *buf, size_t buflen)
Definition: util-print.c:93
LogCustomFormatNode_::data
char data[LOG_NODE_STRLEN]
Definition: log-cf-common.h:67
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
MemBufferFree
void MemBufferFree(MemBuffer *buffer)
Definition: util-buffer.c:86
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
LogCustomFormatNodeFree
void LogCustomFormatNodeFree(LogCustomFormatNode *node)
Frees memory held by a custom format node.
Definition: log-cf-common.c:68
log-cf-common.h
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
LogCustomFormat_::cf_nodes
LogCustomFormatNode * cf_nodes[LOG_MAXN_NODES]
Definition: log-cf-common.h:73
LogCustomFormatAddNode
void LogCustomFormatAddNode(LogCustomFormat *cf, LogCustomFormatNode *node)
Adds a node to custom format.
Definition: log-cf-common.c:185
MemBuffer_::size
uint32_t size
Definition: util-buffer.h:28
TIMESTAMP_DEFAULT_FORMAT
#define TIMESTAMP_DEFAULT_FORMAT
Definition: log-cf-common.h:35
LogCustomFormatAlloc
LogCustomFormat * LogCustomFormatAlloc(void)
Creates a custom format.
Definition: log-cf-common.c:54
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
LOG_NODE_MAXOUTPUTLEN
#define LOG_NODE_MAXOUTPUTLEN
Definition: log-cf-common.h:33
MemBufferCreateNew
MemBuffer * MemBufferCreateNew(uint32_t size)
Definition: util-buffer.c:32
LogCustomFormatParse
int LogCustomFormatParse(LogCustomFormat *cf, const char *format)
Parses and saves format nodes for custom format.
Definition: log-cf-common.c:96
LogCustomFormatNodeAlloc
LogCustomFormatNode * LogCustomFormatNodeAlloc(void)
Creates a custom format node.
Definition: log-cf-common.c:39