/src/suricata7/src/alert-debuglog.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2014 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 Victor Julien <victor@inliniac.net> |
22 | | */ |
23 | | |
24 | | #include "suricata-common.h" |
25 | | #include "suricata.h" |
26 | | |
27 | | #include "detect.h" |
28 | | #include "flow.h" |
29 | | #include "conf.h" |
30 | | #include "stream.h" |
31 | | #include "app-layer-protos.h" |
32 | | |
33 | | #include "threads.h" |
34 | | #include "threadvars.h" |
35 | | #include "tm-threads.h" |
36 | | |
37 | | #include "util-print.h" |
38 | | |
39 | | #include "pkt-var.h" |
40 | | |
41 | | #include "util-unittest.h" |
42 | | |
43 | | #include "util-debug.h" |
44 | | #include "util-validate.h" |
45 | | #include "util-buffer.h" |
46 | | |
47 | | #include "output.h" |
48 | | #include "alert-debuglog.h" |
49 | | #include "util-privs.h" |
50 | | #include "flow-var.h" |
51 | | #include "flow-bit.h" |
52 | | #include "util-var-name.h" |
53 | | #include "util-optimize.h" |
54 | | #include "util-logopenfile.h" |
55 | | #include "util-time.h" |
56 | | |
57 | | #include "stream-tcp-reassemble.h" |
58 | | |
59 | 0 | #define DEFAULT_LOG_FILENAME "alert-debug.log" |
60 | | |
61 | 71 | #define MODULE_NAME "AlertDebugLog" |
62 | | |
63 | | typedef struct AlertDebugLogThread_ { |
64 | | LogFileCtx *file_ctx; |
65 | | /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ |
66 | | MemBuffer *buffer; |
67 | | } AlertDebugLogThread; |
68 | | |
69 | | /** |
70 | | * \brief Function to log the FlowVars into alert-debug.log |
71 | | * |
72 | | * \param aft Pointer to AlertDebugLog Thread |
73 | | * \param p Pointer to the packet |
74 | | * |
75 | | */ |
76 | | static void AlertDebugLogFlowVars(AlertDebugLogThread *aft, const Packet *p) |
77 | 0 | { |
78 | 0 | const GenericVar *gv = p->flow->flowvar; |
79 | 0 | uint16_t i; |
80 | 0 | while (gv != NULL) { |
81 | 0 | if (gv->type == DETECT_FLOWBITS) { |
82 | 0 | FlowBit *fb = (FlowBit *)gv; |
83 | 0 | const char *fbname = VarNameStoreLookupById(fb->idx, VAR_TYPE_FLOW_BIT); |
84 | 0 | if (fbname) { |
85 | 0 | MemBufferWriteString(aft->buffer, "FLOWBIT: %s\n", |
86 | 0 | fbname); |
87 | 0 | } |
88 | 0 | } else if (gv->type == DETECT_FLOWVAR || gv->type == DETECT_FLOWINT) { |
89 | 0 | FlowVar *fv = (FlowVar *) gv; |
90 | |
|
91 | 0 | if (fv->datatype == FLOWVAR_TYPE_STR) { |
92 | 0 | const char *fvname = VarNameStoreLookupById(fv->idx, |
93 | 0 | VAR_TYPE_FLOW_VAR); |
94 | 0 | MemBufferWriteString(aft->buffer, "FLOWVAR: \"%s\" => \"", |
95 | 0 | fvname); |
96 | 0 | for (i = 0; i < fv->data.fv_str.value_len; i++) { |
97 | 0 | if (isprint(fv->data.fv_str.value[i])) { |
98 | 0 | MemBufferWriteString(aft->buffer, "%c", |
99 | 0 | fv->data.fv_str.value[i]); |
100 | 0 | } else { |
101 | 0 | MemBufferWriteString(aft->buffer, "\\%02X", |
102 | 0 | fv->data.fv_str.value[i]); |
103 | 0 | } |
104 | 0 | } |
105 | 0 | MemBufferWriteString(aft->buffer, "\"\n"); |
106 | 0 | } else if (fv->datatype == FLOWVAR_TYPE_INT) { |
107 | 0 | const char *fvname = VarNameStoreLookupById(fv->idx, |
108 | 0 | VAR_TYPE_FLOW_INT); |
109 | 0 | MemBufferWriteString(aft->buffer, "FLOWINT: \"%s\" =>" |
110 | 0 | " %"PRIu32"\n", fvname, fv->data.fv_int.value); |
111 | 0 | } |
112 | 0 | } |
113 | 0 | gv = gv->next; |
114 | 0 | } |
115 | 0 | } |
116 | | |
117 | | /** |
118 | | * \brief Function to log the PktVars into alert-debug.log |
119 | | * |
120 | | * \param aft Pointer to AlertDebugLog Thread |
121 | | * \param p Pointer to the packet |
122 | | * |
123 | | */ |
124 | | static void AlertDebugLogPktVars(AlertDebugLogThread *aft, const Packet *p) |
125 | 0 | { |
126 | 0 | const PktVar *pv = p->pktvar; |
127 | |
|
128 | 0 | while (pv != NULL) { |
129 | 0 | const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR); |
130 | 0 | MemBufferWriteString(aft->buffer, "PKTVAR: %s\n", varname); |
131 | 0 | PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, |
132 | 0 | pv->value, pv->value_len); |
133 | 0 | pv = pv->next; |
134 | 0 | } |
135 | 0 | } |
136 | | |
137 | | /** \todo doc |
138 | | * assume we have aft lock */ |
139 | | static int AlertDebugPrintStreamSegmentCallback( |
140 | | const Packet *p, TcpSegment *seg, void *data, const uint8_t *buf, uint32_t buflen) |
141 | 0 | { |
142 | 0 | AlertDebugLogThread *aft = (AlertDebugLogThread *)data; |
143 | |
|
144 | 0 | MemBufferWriteString(aft->buffer, "STREAM DATA LEN: %"PRIu32"\n", buflen); |
145 | 0 | MemBufferWriteString(aft->buffer, "STREAM DATA:\n"); |
146 | |
|
147 | 0 | PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, |
148 | 0 | buf, buflen); |
149 | |
|
150 | 0 | return 1; |
151 | 0 | } |
152 | | |
153 | | static TmEcode AlertDebugLogger(ThreadVars *tv, const Packet *p, void *thread_data) |
154 | 0 | { |
155 | 0 | AlertDebugLogThread *aft = (AlertDebugLogThread *)thread_data; |
156 | 0 | int i; |
157 | 0 | char timebuf[64]; |
158 | 0 | const char *pkt_src_str = NULL; |
159 | |
|
160 | 0 | if (p->alerts.cnt == 0) |
161 | 0 | return TM_ECODE_OK; |
162 | | |
163 | 0 | MemBufferReset(aft->buffer); |
164 | |
|
165 | 0 | CreateTimeString(p->ts, timebuf, sizeof(timebuf)); |
166 | |
|
167 | 0 | MemBufferWriteString(aft->buffer, "+================\n" |
168 | 0 | "TIME: %s\n", timebuf); |
169 | 0 | if (p->pcap_cnt > 0) { |
170 | 0 | MemBufferWriteString(aft->buffer, "PCAP PKT NUM: %"PRIu64"\n", p->pcap_cnt); |
171 | 0 | } |
172 | 0 | pkt_src_str = PktSrcToString(p->pkt_src); |
173 | 0 | MemBufferWriteString(aft->buffer, "PKT SRC: %s\n", pkt_src_str); |
174 | |
|
175 | 0 | char srcip[46], dstip[46]; |
176 | 0 | if (PKT_IS_IPV4(p)) { |
177 | 0 | PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); |
178 | 0 | PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); |
179 | 0 | } else { |
180 | 0 | DEBUG_VALIDATE_BUG_ON(!(PKT_IS_IPV6(p))); |
181 | 0 | PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); |
182 | 0 | PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); |
183 | 0 | } |
184 | | |
185 | 0 | MemBufferWriteString(aft->buffer, "SRC IP: %s\n" |
186 | 0 | "DST IP: %s\n" |
187 | 0 | "PROTO: %" PRIu32 "\n", |
188 | 0 | srcip, dstip, p->proto); |
189 | 0 | if (PKT_IS_TCP(p) || PKT_IS_UDP(p)) { |
190 | 0 | MemBufferWriteString(aft->buffer, "SRC PORT: %" PRIu32 "\n" |
191 | 0 | "DST PORT: %" PRIu32 "\n", |
192 | 0 | p->sp, p->dp); |
193 | 0 | if (PKT_IS_TCP(p)) { |
194 | 0 | MemBufferWriteString(aft->buffer, "TCP SEQ: %"PRIu32"\n" |
195 | 0 | "TCP ACK: %"PRIu32"\n", |
196 | 0 | TCP_GET_SEQ(p), TCP_GET_ACK(p)); |
197 | 0 | } |
198 | 0 | } |
199 | | |
200 | | /* flow stuff */ |
201 | 0 | MemBufferWriteString(aft->buffer, "FLOW: to_server: %s, " |
202 | 0 | "to_client: %s\n", |
203 | 0 | p->flowflags & FLOW_PKT_TOSERVER ? "TRUE" : "FALSE", |
204 | 0 | p->flowflags & FLOW_PKT_TOCLIENT ? "TRUE" : "FALSE"); |
205 | |
|
206 | 0 | if (p->flow != NULL) { |
207 | 0 | int applayer = 0; |
208 | 0 | applayer = StreamTcpAppLayerIsDisabled(p->flow); |
209 | 0 | CreateTimeString(p->flow->startts, timebuf, sizeof(timebuf)); |
210 | 0 | MemBufferWriteString(aft->buffer, "FLOW Start TS: %s\n", timebuf); |
211 | 0 | MemBufferWriteString(aft->buffer, "FLOW PKTS TODST: %"PRIu32"\n" |
212 | 0 | "FLOW PKTS TOSRC: %"PRIu32"\n" |
213 | 0 | "FLOW Total Bytes: %"PRIu64"\n", |
214 | 0 | p->flow->todstpktcnt, p->flow->tosrcpktcnt, |
215 | 0 | p->flow->todstbytecnt + p->flow->tosrcbytecnt); |
216 | 0 | MemBufferWriteString(aft->buffer, |
217 | 0 | "FLOW ACTION: DROP: %s\n" |
218 | 0 | "FLOW NOINSPECTION: PACKET: %s, PAYLOAD: %s, APP_LAYER: %s\n" |
219 | 0 | "FLOW APP_LAYER: DETECTED: %s, PROTO %" PRIu16 "\n", |
220 | 0 | p->flow->flags & FLOW_ACTION_DROP ? "TRUE" : "FALSE", |
221 | 0 | p->flow->flags & FLOW_NOPACKET_INSPECTION ? "TRUE" : "FALSE", |
222 | 0 | p->flow->flags & FLOW_NOPAYLOAD_INSPECTION ? "TRUE" : "FALSE", |
223 | 0 | applayer ? "TRUE" : "FALSE", |
224 | 0 | (p->flow->alproto != ALPROTO_UNKNOWN) ? "TRUE" : "FALSE", p->flow->alproto); |
225 | 0 | AlertDebugLogFlowVars(aft, p); |
226 | 0 | } |
227 | |
|
228 | 0 | AlertDebugLogPktVars(aft, p); |
229 | | |
230 | | /* any stuff */ |
231 | | /* Sig details? */ |
232 | |
|
233 | 0 | MemBufferWriteString(aft->buffer, |
234 | 0 | "PACKET LEN: %" PRIu32 "\n" |
235 | 0 | "PACKET:\n", |
236 | 0 | GET_PKT_LEN(p)); |
237 | 0 | PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, |
238 | 0 | GET_PKT_DATA(p), GET_PKT_LEN(p)); |
239 | |
|
240 | 0 | MemBufferWriteString(aft->buffer, "ALERT CNT: %" PRIu32 "\n", |
241 | 0 | p->alerts.cnt); |
242 | |
|
243 | 0 | for (i = 0; i < p->alerts.cnt; i++) { |
244 | 0 | const PacketAlert *pa = &p->alerts.alerts[i]; |
245 | 0 | if (unlikely(pa->s == NULL)) { |
246 | 0 | continue; |
247 | 0 | } |
248 | | |
249 | 0 | MemBufferWriteString(aft->buffer, |
250 | 0 | "ALERT MSG [%02d]: %s\n" |
251 | 0 | "ALERT GID [%02d]: %" PRIu32 "\n" |
252 | 0 | "ALERT SID [%02d]: %" PRIu32 "\n" |
253 | 0 | "ALERT REV [%02d]: %" PRIu32 "\n" |
254 | 0 | "ALERT CLASS [%02d]: %s\n" |
255 | 0 | "ALERT PRIO [%02d]: %" PRIu32 "\n" |
256 | 0 | "ALERT FOUND IN [%02d]: %s\n", |
257 | 0 | i, pa->s->msg, |
258 | 0 | i, pa->s->gid, |
259 | 0 | i, pa->s->id, |
260 | 0 | i, pa->s->rev, |
261 | 0 | i, pa->s->class_msg ? pa->s->class_msg : "<none>", |
262 | 0 | i, pa->s->prio, |
263 | 0 | i, |
264 | 0 | pa->flags & PACKET_ALERT_FLAG_STREAM_MATCH ? "STREAM" : |
265 | 0 | (pa->flags & PACKET_ALERT_FLAG_STATE_MATCH ? "STATE" : "PACKET")); |
266 | 0 | if (pa->flags & PACKET_ALERT_FLAG_TX) { |
267 | 0 | MemBufferWriteString(aft->buffer, |
268 | 0 | "ALERT IN TX [%02d]: %"PRIu64"\n", i, pa->tx_id); |
269 | 0 | } else { |
270 | 0 | MemBufferWriteString(aft->buffer, |
271 | 0 | "ALERT IN TX [%02d]: N/A\n", i); |
272 | 0 | } |
273 | 0 | if (p->payload_len > 0) { |
274 | 0 | MemBufferWriteString(aft->buffer, |
275 | 0 | "PAYLOAD LEN: %" PRIu32 "\n" |
276 | 0 | "PAYLOAD:\n", |
277 | 0 | p->payload_len); |
278 | 0 | PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, |
279 | 0 | p->payload, p->payload_len); |
280 | 0 | } |
281 | 0 | if ((pa->flags & PACKET_ALERT_FLAG_STATE_MATCH) || |
282 | 0 | (pa->flags & PACKET_ALERT_FLAG_STREAM_MATCH)) { |
283 | | /* This is an app layer or stream alert */ |
284 | 0 | int ret; |
285 | 0 | uint8_t flag; |
286 | 0 | if (!(PKT_IS_TCP(p)) || p->flow == NULL || |
287 | 0 | p->flow->protoctx == NULL) { |
288 | 0 | continue; |
289 | 0 | } |
290 | | /* IDS mode reverse the data */ |
291 | | /** \todo improve the order selection policy */ |
292 | 0 | if (p->flowflags & FLOW_PKT_TOSERVER) { |
293 | 0 | flag = STREAM_DUMP_TOCLIENT; |
294 | 0 | } else { |
295 | 0 | flag = STREAM_DUMP_TOSERVER; |
296 | 0 | } |
297 | 0 | ret = StreamSegmentForEach((const Packet *)p, flag, |
298 | 0 | AlertDebugPrintStreamSegmentCallback, |
299 | 0 | (void *)aft); |
300 | 0 | if (ret < 0) { |
301 | 0 | return TM_ECODE_FAILED; |
302 | 0 | } |
303 | 0 | } |
304 | 0 | } |
305 | | |
306 | 0 | aft->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer), |
307 | 0 | MEMBUFFER_OFFSET(aft->buffer), aft->file_ctx); |
308 | |
|
309 | 0 | return TM_ECODE_OK; |
310 | 0 | } |
311 | | |
312 | | static TmEcode AlertDebugLogDecoderEvent(ThreadVars *tv, const Packet *p, void *thread_data) |
313 | 0 | { |
314 | 0 | AlertDebugLogThread *aft = (AlertDebugLogThread *)thread_data; |
315 | 0 | int i; |
316 | 0 | char timebuf[64]; |
317 | 0 | const char *pkt_src_str = NULL; |
318 | |
|
319 | 0 | if (p->alerts.cnt == 0) |
320 | 0 | return TM_ECODE_OK; |
321 | | |
322 | 0 | MemBufferReset(aft->buffer); |
323 | |
|
324 | 0 | CreateTimeString(p->ts, timebuf, sizeof(timebuf)); |
325 | |
|
326 | 0 | MemBufferWriteString(aft->buffer, |
327 | 0 | "+================\n" |
328 | 0 | "TIME: %s\n", timebuf); |
329 | 0 | if (p->pcap_cnt > 0) { |
330 | 0 | MemBufferWriteString(aft->buffer, |
331 | 0 | "PCAP PKT NUM: %"PRIu64"\n", p->pcap_cnt); |
332 | 0 | } |
333 | 0 | pkt_src_str = PktSrcToString(p->pkt_src); |
334 | 0 | MemBufferWriteString(aft->buffer, "PKT SRC: %s\n", pkt_src_str); |
335 | 0 | MemBufferWriteString(aft->buffer, |
336 | 0 | "ALERT CNT: %" PRIu32 "\n", p->alerts.cnt); |
337 | |
|
338 | 0 | for (i = 0; i < p->alerts.cnt; i++) { |
339 | 0 | const PacketAlert *pa = &p->alerts.alerts[i]; |
340 | 0 | if (unlikely(pa->s == NULL)) { |
341 | 0 | continue; |
342 | 0 | } |
343 | | |
344 | 0 | MemBufferWriteString(aft->buffer, |
345 | 0 | "ALERT MSG [%02d]: %s\n" |
346 | 0 | "ALERT GID [%02d]: %" PRIu32 "\n" |
347 | 0 | "ALERT SID [%02d]: %" PRIu32 "\n" |
348 | 0 | "ALERT REV [%02d]: %" PRIu32 "\n" |
349 | 0 | "ALERT CLASS [%02d]: %s\n" |
350 | 0 | "ALERT PRIO [%02d]: %" PRIu32 "\n", |
351 | 0 | i, pa->s->msg, |
352 | 0 | i, pa->s->gid, |
353 | 0 | i, pa->s->id, |
354 | 0 | i, pa->s->rev, |
355 | 0 | i, pa->s->class_msg, |
356 | 0 | i, pa->s->prio); |
357 | 0 | } |
358 | |
|
359 | 0 | MemBufferWriteString(aft->buffer, |
360 | 0 | "PACKET LEN: %" PRIu32 "\n" |
361 | 0 | "PACKET:\n", |
362 | 0 | GET_PKT_LEN(p)); |
363 | 0 | PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size, |
364 | 0 | GET_PKT_DATA(p), GET_PKT_LEN(p)); |
365 | |
|
366 | 0 | aft->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer), |
367 | 0 | MEMBUFFER_OFFSET(aft->buffer), aft->file_ctx); |
368 | |
|
369 | 0 | return TM_ECODE_OK; |
370 | 0 | } |
371 | | |
372 | | static TmEcode AlertDebugLogThreadInit(ThreadVars *t, const void *initdata, void **data) |
373 | 0 | { |
374 | 0 | AlertDebugLogThread *aft = SCMalloc(sizeof(AlertDebugLogThread)); |
375 | 0 | if (unlikely(aft == NULL)) |
376 | 0 | return TM_ECODE_FAILED; |
377 | 0 | memset(aft, 0, sizeof(AlertDebugLogThread)); |
378 | |
|
379 | 0 | if(initdata == NULL) |
380 | 0 | { |
381 | 0 | SCLogDebug("Error getting context for AlertDebugLog. \"initdata\" argument NULL"); |
382 | 0 | SCFree(aft); |
383 | 0 | return TM_ECODE_FAILED; |
384 | 0 | } |
385 | | /** Use the Output Context (file pointer and mutex) */ |
386 | 0 | aft->file_ctx = ((OutputCtx *)initdata)->data; |
387 | | |
388 | | /* 1 mb seems sufficient enough */ |
389 | 0 | aft->buffer = MemBufferCreateNew(1 * 1024 * 1024); |
390 | 0 | if (aft->buffer == NULL) { |
391 | 0 | SCFree(aft); |
392 | 0 | return TM_ECODE_FAILED; |
393 | 0 | } |
394 | | |
395 | 0 | *data = (void *)aft; |
396 | 0 | return TM_ECODE_OK; |
397 | 0 | } |
398 | | |
399 | | static TmEcode AlertDebugLogThreadDeinit(ThreadVars *t, void *data) |
400 | 0 | { |
401 | 0 | AlertDebugLogThread *aft = (AlertDebugLogThread *)data; |
402 | 0 | if (aft == NULL) { |
403 | 0 | return TM_ECODE_OK; |
404 | 0 | } |
405 | | |
406 | 0 | MemBufferFree(aft->buffer); |
407 | | /* clear memory */ |
408 | 0 | memset(aft, 0, sizeof(AlertDebugLogThread)); |
409 | |
|
410 | 0 | SCFree(aft); |
411 | 0 | return TM_ECODE_OK; |
412 | 0 | } |
413 | | |
414 | | static void AlertDebugLogDeInitCtx(OutputCtx *output_ctx) |
415 | 0 | { |
416 | 0 | if (output_ctx != NULL) { |
417 | 0 | LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data; |
418 | 0 | if (logfile_ctx != NULL) { |
419 | 0 | LogFileFreeCtx(logfile_ctx); |
420 | 0 | } |
421 | 0 | SCFree(output_ctx); |
422 | 0 | } |
423 | 0 | } |
424 | | |
425 | | /** |
426 | | * \brief Create a new LogFileCtx for alert debug logging. |
427 | | * |
428 | | * \param ConfNode containing configuration for this logger. |
429 | | * |
430 | | * \return output_ctx if succesful, NULL otherwise |
431 | | */ |
432 | | static OutputInitResult AlertDebugLogInitCtx(ConfNode *conf) |
433 | 0 | { |
434 | 0 | OutputInitResult result = { NULL, false }; |
435 | 0 | LogFileCtx *file_ctx = NULL; |
436 | |
|
437 | 0 | file_ctx = LogFileNewCtx(); |
438 | 0 | if (file_ctx == NULL) { |
439 | 0 | SCLogDebug("couldn't create new file_ctx"); |
440 | 0 | goto error; |
441 | 0 | } |
442 | | |
443 | 0 | if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { |
444 | 0 | goto error; |
445 | 0 | } |
446 | | |
447 | 0 | OutputCtx *output_ctx = SCMalloc(sizeof(OutputCtx)); |
448 | 0 | if (unlikely(output_ctx == NULL)) |
449 | 0 | goto error; |
450 | | |
451 | 0 | memset(output_ctx, 0x00, sizeof(OutputCtx)); |
452 | 0 | output_ctx->data = file_ctx; |
453 | 0 | output_ctx->DeInit = AlertDebugLogDeInitCtx; |
454 | |
|
455 | 0 | SCLogDebug("Alert debug log output initialized"); |
456 | 0 | result.ctx = output_ctx; |
457 | 0 | result.ok = true; |
458 | 0 | return result; |
459 | | |
460 | 0 | error: |
461 | 0 | if (file_ctx != NULL) { |
462 | 0 | LogFileFreeCtx(file_ctx); |
463 | 0 | } |
464 | |
|
465 | 0 | return result; |
466 | 0 | } |
467 | | |
468 | | static int AlertDebugLogCondition(ThreadVars *tv, void *thread_data, const Packet *p) |
469 | 0 | { |
470 | 0 | return (p->alerts.cnt ? TRUE : FALSE); |
471 | 0 | } |
472 | | |
473 | | static int AlertDebugLogLogger(ThreadVars *tv, void *thread_data, const Packet *p) |
474 | 0 | { |
475 | 0 | if (PKT_IS_IPV4(p) || PKT_IS_IPV6(p)) { |
476 | 0 | return AlertDebugLogger(tv, p, thread_data); |
477 | 0 | } else if (p->events.cnt > 0) { |
478 | 0 | return AlertDebugLogDecoderEvent(tv, p, thread_data); |
479 | 0 | } |
480 | 0 | return TM_ECODE_OK; |
481 | 0 | } |
482 | | |
483 | | void AlertDebugLogRegister(void) |
484 | 71 | { |
485 | 71 | OutputRegisterPacketModule(LOGGER_ALERT_DEBUG, MODULE_NAME, "alert-debug", |
486 | 71 | AlertDebugLogInitCtx, AlertDebugLogLogger, AlertDebugLogCondition, |
487 | | AlertDebugLogThreadInit, AlertDebugLogThreadDeinit, NULL); |
488 | 71 | } |