suricata
app-layer-enip.c
Go to the documentation of this file.
1 /* Copyright (C) 2015 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 Kevin Wong <kwong@solananetworks.com>
22  *
23  * App-layer parser for ENIP protocol
24  *
25  */
26 
27 #include "suricata-common.h"
28 
29 #include "util-debug.h"
30 #include "util-byte.h"
31 #include "util-enum.h"
32 #include "util-mem.h"
33 #include "util-misc.h"
34 
35 #include "stream.h"
36 
37 #include "app-layer-protos.h"
38 #include "app-layer-parser.h"
39 #include "app-layer-enip.h"
40 #include "app-layer-enip-common.h"
41 
42 #include "app-layer-detect-proto.h"
43 
44 #include "conf.h"
45 #include "decode.h"
46 
47 #include "detect-parse.h"
48 #include "detect-engine.h"
49 #include "util-byte.h"
50 #include "util-unittest.h"
51 #include "util-unittest-helper.h"
52 #include "pkt-var.h"
53 #include "util-profiling.h"
54 
55 
57  { NULL, -1 },
58 };
59 
60 /** \brief get value for 'complete' status in ENIP
61  *
62  * For ENIP we use a simple bool.
63  */
64 static int ENIPGetAlstateProgress(void *tx, uint8_t direction)
65 {
66  return 1;
67 }
68 
69 /** \brief get value for 'complete' status in ENIP
70  *
71  * For ENIP we use a simple bool.
72  */
73 static int ENIPGetAlstateProgressCompletionStatus(uint8_t direction)
74 {
75  return 1;
76 }
77 
78 static DetectEngineState *ENIPGetTxDetectState(void *vtx)
79 {
80  ENIPTransaction *tx = (ENIPTransaction *)vtx;
81  return tx->de_state;
82 }
83 
84 static int ENIPSetTxDetectState(void *vtx, DetectEngineState *s)
85 {
86  ENIPTransaction *tx = (ENIPTransaction *)vtx;
87  tx->de_state = s;
88  return 0;
89 }
90 
91 static void *ENIPGetTx(void *alstate, uint64_t tx_id)
92 {
93  ENIPState *enip = (ENIPState *) alstate;
94  ENIPTransaction *tx = NULL;
95 
96  if (enip->curr && enip->curr->tx_num == tx_id + 1)
97  return enip->curr;
98 
99  TAILQ_FOREACH(tx, &enip->tx_list, next) {
100  if (tx->tx_num != (tx_id+1))
101  continue;
102 
103  SCLogDebug("returning tx %p", tx);
104  return tx;
105  }
106 
107  return NULL;
108 }
109 
110 static uint64_t ENIPGetTxCnt(void *alstate)
111 {
112  return ((uint64_t) ((ENIPState *) alstate)->transaction_max);
113 }
114 
115 static AppLayerDecoderEvents *ENIPGetEvents(void *state, uint64_t id)
116 {
117  ENIPState *enip = (ENIPState *) state;
118  ENIPTransaction *tx;
119 
120  if (enip->curr && enip->curr->tx_num == (id + 1))
121  return enip->curr->decoder_events;
122 
123  TAILQ_FOREACH(tx, &enip->tx_list, next) {
124  if (tx->tx_num == (id+1))
125  return tx->decoder_events;
126  }
127 
128  return NULL;
129 }
130 
131 static int ENIPStateGetEventInfo(const char *event_name, int *event_id, AppLayerEventType *event_type)
132 {
133  *event_id = SCMapEnumNameToValue(event_name, enip_decoder_event_table);
134 
135  if (*event_id == -1) {
136  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
137  "enip's enum map table.", event_name);
138  /* yes this is fatal */
139  return -1;
140  }
141 
142  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
143 
144  return 0;
145 }
146 
147 /** \brief Allocate enip state
148  *
149  * return state
150  */
151 static void *ENIPStateAlloc(void)
152 {
153  SCLogDebug("ENIPStateAlloc");
154  void *s = SCMalloc(sizeof(ENIPState));
155  if (unlikely(s == NULL))
156  return NULL;
157 
158  memset(s, 0, sizeof(ENIPState));
159 
160  ENIPState *enip_state = (ENIPState *) s;
161 
162  TAILQ_INIT(&enip_state->tx_list);
163  return s;
164 }
165 
166 /** \internal
167  * \brief Free a ENIP TX
168  * \param tx ENIP TX to free */
169 static void ENIPTransactionFree(ENIPTransaction *tx, ENIPState *state)
170 {
171  SCEnter();
172  SCLogDebug("ENIPTransactionFree");
173  CIPServiceEntry *svc = NULL;
174  while ((svc = TAILQ_FIRST(&tx->service_list)))
175  {
176  TAILQ_REMOVE(&tx->service_list, svc, next);
177 
178  SegmentEntry *seg = NULL;
179  while ((seg = TAILQ_FIRST(&svc->segment_list)))
180  {
181  TAILQ_REMOVE(&svc->segment_list, seg, next);
182  SCFree(seg);
183  }
184 
185  AttributeEntry *attr = NULL;
186  while ((attr = TAILQ_FIRST(&svc->attrib_list)))
187  {
188  TAILQ_REMOVE(&svc->attrib_list, attr, next);
189  SCFree(attr);
190  }
191 
192  SCFree(svc);
193  }
194 
196 
197  if (tx->de_state != NULL)
198  {
200 
201  state->tx_with_detect_state_cnt--;
202  }
203 
204  if (state->iter == tx)
205  state->iter = NULL;
206 
207  SCFree(tx);
208  SCReturn;
209 }
210 
211 /** \brief Free enip state
212  *
213  */
214 static void ENIPStateFree(void *s)
215 {
216  SCEnter();
217  SCLogDebug("ENIPStateFree");
218  if (s)
219  {
220  ENIPState *enip_state = (ENIPState *) s;
221 
222  ENIPTransaction *tx = NULL;
223  while ((tx = TAILQ_FIRST(&enip_state->tx_list)))
224  {
225  TAILQ_REMOVE(&enip_state->tx_list, tx, next);
226  ENIPTransactionFree(tx, enip_state);
227  }
228 
229  if (enip_state->buffer != NULL)
230  {
231  SCFree(enip_state->buffer);
232  }
233 
234  SCFree(s);
235  }
236  SCReturn;
237 }
238 
239 /** \internal
240  * \brief Allocate a ENIP TX
241  * \retval tx or NULL */
242 static ENIPTransaction *ENIPTransactionAlloc(ENIPState *state)
243 {
244  SCLogDebug("ENIPStateTransactionAlloc");
246  sizeof(ENIPTransaction));
247  if (unlikely(tx == NULL))
248  return NULL;
249 
250  state->curr = tx;
251  state->transaction_max++;
252 
253  memset(tx, 0x00, sizeof(ENIPTransaction));
254  TAILQ_INIT(&tx->service_list);
255 
256  tx->enip = state;
257  tx->tx_num = state->transaction_max;
258  tx->service_count = 0;
259 
260  TAILQ_INSERT_TAIL(&state->tx_list, tx, next);
261 
262  return tx;
263 }
264 
265 /**
266  * \brief enip transaction cleanup callback
267  */
268 static void ENIPStateTransactionFree(void *state, uint64_t tx_id)
269 {
270  SCEnter();
271  SCLogDebug("ENIPStateTransactionFree");
272  ENIPState *enip_state = state;
273  ENIPTransaction *tx = NULL;
274  TAILQ_FOREACH(tx, &enip_state->tx_list, next)
275  {
276 
277  if ((tx_id+1) < tx->tx_num)
278  break;
279  else if ((tx_id+1) > tx->tx_num)
280  continue;
281 
282  if (tx == enip_state->curr)
283  enip_state->curr = NULL;
284 
285  if (tx->decoder_events != NULL)
286  {
287  if (tx->decoder_events->cnt <= enip_state->events)
288  enip_state->events -= tx->decoder_events->cnt;
289  else
290  enip_state->events = 0;
291  }
292 
293  TAILQ_REMOVE(&enip_state->tx_list, tx, next);
294  ENIPTransactionFree(tx, state);
295  break;
296  }
297  SCReturn;
298 }
299 
300 /** \internal
301  *
302  * \brief This function is called to retrieve a ENIP
303  *
304  * \param state ENIP state structure for the parser
305  * \param input Input line of the command
306  * \param input_len Length of the request
307  *
308  * \retval 1 when the command is parsed, 0 otherwise
309  */
310 static int ENIPParse(Flow *f, void *state, AppLayerParserState *pstate,
311  uint8_t *input, uint32_t input_len, void *local_data,
312  const uint8_t flags)
313 {
314  SCEnter();
315  ENIPState *enip = (ENIPState *) state;
316  ENIPTransaction *tx;
317 
318  if (input == NULL && AppLayerParserStateIssetFlag(pstate,
320  {
321  SCReturnInt(1);
322  } else if (input == NULL && input_len != 0) {
323  // GAP
324  SCReturnInt(0);
325  } else if (input == NULL || input_len == 0)
326  {
327  SCReturnInt(-1);
328  }
329 
330  while (input_len > 0)
331  {
332  tx = ENIPTransactionAlloc(enip);
333  if (tx == NULL)
334  SCReturnInt(0);
335 
336  SCLogDebug("ENIPParse input len %d", input_len);
337  DecodeENIPPDU(input, input_len, tx);
338  uint32_t pkt_len = tx->header.length + sizeof(ENIPEncapHdr);
339  SCLogDebug("ENIPParse packet len %d", pkt_len);
340  if (pkt_len > input_len)
341  {
342  SCLogDebug("Invalid packet length");
343  break;
344  }
345 
346  input += pkt_len;
347  input_len -= pkt_len;
348  //SCLogDebug("remaining %d", input_len);
349 
350  if (input_len < sizeof(ENIPEncapHdr))
351  {
352  //SCLogDebug("Not enough data"); //not enough data for ENIP
353  break;
354  }
355  }
356 
357  return 1;
358 }
359 
360 
361 
362 static uint16_t ENIPProbingParser(Flow *f, uint8_t direction,
363  uint8_t *input, uint32_t input_len, uint8_t *rdir)
364 {
365  // SCLogDebug("ENIPProbingParser %d", input_len);
366  if (input_len < sizeof(ENIPEncapHdr))
367  {
368  SCLogDebug("length too small to be a ENIP header");
369  return ALPROTO_UNKNOWN;
370  }
371 
372  return ALPROTO_ENIP;
373 }
374 
375 /**
376  * \brief Function to register the ENIP protocol parsers and other functions
377  */
379 {
380  SCEnter();
381  const char *proto_name = "enip";
382 
383  if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name))
384  {
386 
387  if (RunmodeIsUnittests())
388  {
389  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818", ALPROTO_ENIP,
390  0, sizeof(ENIPEncapHdr), STREAM_TOSERVER, ENIPProbingParser, NULL);
391 
392  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818", ALPROTO_ENIP,
393  0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT, ENIPProbingParser, NULL);
394 
395  } else
396  {
397  if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
398  proto_name, ALPROTO_ENIP, 0, sizeof(ENIPEncapHdr),
399  ENIPProbingParser, ENIPProbingParser))
400  {
401  SCLogDebug(
402  "no ENIP UDP config found enabling ENIP detection on port 44818.");
403 
404  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818",
406  ENIPProbingParser, NULL);
407 
408  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818",
410  ENIPProbingParser, NULL);
411  }
412  }
413 
414  } else
415  {
416  SCLogConfig("Protocol detection and parser disabled for %s protocol.",
417  proto_name);
418  return;
419  }
420 
421  if (AppLayerParserConfParserEnabled("udp", proto_name))
422  {
424  STREAM_TOSERVER, ENIPParse);
426  STREAM_TOCLIENT, ENIPParse);
427 
429  ENIPStateAlloc, ENIPStateFree);
430 
431  AppLayerParserRegisterGetEventsFunc(IPPROTO_UDP, ALPROTO_ENIP, ENIPGetEvents);
432 
434  ENIPGetTxDetectState, ENIPSetTxDetectState);
435 
436  AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_ENIP, ENIPGetTx);
437  AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_ENIP, ENIPGetTxCnt);
438  AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_ENIP, ENIPStateTransactionFree);
439 
440  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_UDP, ALPROTO_ENIP, ENIPGetAlstateProgress);
441  AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_ENIP, ENIPGetAlstateProgressCompletionStatus);
442 
443  AppLayerParserRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_ENIP, ENIPStateGetEventInfo);
444 
447 
448  } else
449  {
450  SCLogInfo(
451  "Parsed disabled for %s protocol. Protocol detection" "still on.",
452  proto_name);
453  }
454 
455 #ifdef UNITTESTS
457 #endif
458 
459  SCReturn;
460 }
461 
462 /**
463  * \brief Function to register the ENIP protocol parsers and other functions
464  */
466 {
467  SCEnter();
468  const char *proto_name = "enip";
469 
470  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name))
471  {
473 
474  if (RunmodeIsUnittests())
475  {
476  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "44818", ALPROTO_ENIP,
477  0, sizeof(ENIPEncapHdr), STREAM_TOSERVER, ENIPProbingParser, NULL);
478 
479  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "44818", ALPROTO_ENIP,
480  0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT, ENIPProbingParser, NULL);
481 
482  } else
483  {
484  if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
485  proto_name, ALPROTO_ENIP, 0, sizeof(ENIPEncapHdr),
486  ENIPProbingParser, ENIPProbingParser))
487  {
488 #ifndef AFLFUZZ_APPLAYER
489  return;
490 #endif
491  }
492  }
493 
494  } else
495  {
496  SCLogDebug("Protocol detection and parser disabled for %s protocol.",
497  proto_name);
498  return;
499  }
500 
501  if (AppLayerParserConfParserEnabled("tcp", proto_name))
502  {
504  STREAM_TOSERVER, ENIPParse);
506  STREAM_TOCLIENT, ENIPParse);
508  ENIPStateAlloc, ENIPStateFree);
509 
510  AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_ENIP, ENIPGetEvents);
511 
513  ENIPGetTxDetectState, ENIPSetTxDetectState);
514 
515  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_ENIP, ENIPGetTx);
516  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_ENIP, ENIPGetTxCnt);
517  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_ENIP, ENIPStateTransactionFree);
518 
519  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_ENIP, ENIPGetAlstateProgress);
520  AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_ENIP, ENIPGetAlstateProgressCompletionStatus);
521 
522  AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_ENIP, ENIPStateGetEventInfo);
523 
526 
527  /* This parser accepts gaps. */
530 
531  } else
532  {
533  SCLogConfig("Parser disabled for %s protocol. Protocol detection still on.",
534  proto_name);
535  }
536 
537 #ifdef UNITTESTS
539 #endif
540 
541  SCReturn;
542 }
543 
544 /* UNITTESTS */
545 #ifdef UNITTESTS
546 #include "app-layer-parser.h"
547 #include "detect-parse.h"
548 #include "detect-engine.h"
549 #include "flow-util.h"
550 #include "stream-tcp.h"
551 #include "util-unittest.h"
552 #include "util-unittest-helper.h"
553 
554 static uint8_t listIdentity[] = {/* List ID */ 0x63, 0x00,
555  /* Length */ 0x00, 0x00,
556  /* Session */ 0x00, 0x00, 0x00, 0x00,
557  /* Status */ 0x00, 0x00, 0x00, 0x00,
558  /* Delay*/ 0x00,
559  /* Context */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560  /* Quantity of coils */ 0x00, 0x00, 0x00, 0x00, 0x00};
561 
562 /**
563  * \brief Test if ENIP Packet matches signature
564  */
565 static int ALDecodeENIPTest(void)
566 {
568  Flow f;
569  TcpSession ssn;
570 
571  memset(&f, 0, sizeof(f));
572  memset(&ssn, 0, sizeof(ssn));
573 
574  f.protoctx = (void *)&ssn;
575  f.proto = IPPROTO_TCP;
576  f.alproto = ALPROTO_ENIP;
577 
579 
580  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_ENIP, STREAM_TOSERVER,
581  listIdentity, sizeof(listIdentity));
582  FAIL_IF(r != 0);
583 
584  ENIPState *enip_state = f.alstate;
585  FAIL_IF_NULL(enip_state);
586 
587  ENIPTransaction *tx = ENIPGetTx(enip_state, 0);
588  FAIL_IF_NULL(tx);
589 
590  FAIL_IF(tx->header.command != 99);
591 
592  AppLayerParserThreadCtxFree(alp_tctx);
594  FLOW_DESTROY(&f);
595 
596  PASS;
597 }
598 
599 #endif /* UNITTESTS */
600 
602 {
603 #ifdef UNITTESTS
604  UtRegisterTest("ALDecodeENIPTest", ALDecodeENIPTest);
605 #endif /* UNITTESTS */
606 }
struct ENIPState_ * enip
enum AppLayerEventType_ AppLayerEventType
uint16_t flags
#define SCLogDebug(...)
Definition: util-debug.h:335
void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto, uint32_t flags)
#define TAILQ_FIRST(head)
Definition: queue.h:339
void AppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
struct HtpBodyChunk_ * next
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
uint32_t event_type
uint8_t proto
Definition: flow.h:344
ENIPTransaction * iter
#define PASS
Pass the test.
#define unlikely(expr)
Definition: util-optimize.h:35
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
uint64_t transaction_max
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
Definition: util-enum.c:41
#define TRUE
void * protoctx
Definition: flow.h:400
ENIPTransaction * curr
void * alstate
Definition: flow.h:438
int AppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests and when...
void RegisterENIPUDPParsers(void)
Function to register the ENIP protocol parsers and other functions.
#define SCCalloc(nm, a)
Definition: util-mem.h:197
Data structure to store app layer decoder events.
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
#define TAILQ_INIT(head)
Definition: queue.h:370
uint64_t tx_with_detect_state_cnt
int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, int *event_id, AppLayerEventType *event_type))
SCEnumCharMap enip_decoder_event_table[]
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
Per flow ENIP state container.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:412
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
#define STREAM_TOCLIENT
Definition: stream.h:32
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
void ENIPParserRegisterTests(void)
int RunmodeIsUnittests(void)
Definition: suricata.c:259
#define SCReturnInt(x)
Definition: util-debug.h:341
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:385
DetectEngineState * de_state
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
void RegisterENIPTCPParsers(void)
Function to register the ENIP protocol parsers and other functions.
#define SCMalloc(a)
Definition: util-mem.h:166
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
#define SCFree(a)
Definition: util-mem.h:228
uint16_t tx_id
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
AppLayerDecoderEvents * decoder_events
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
#define STREAM_TOSERVER
Definition: stream.h:31
#define APP_LAYER_PARSER_OPT_ACCEPT_GAPS
#define APP_LAYER_PARSER_EOF
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
struct ENIPEncapHdr_ ENIPEncapHdr
#define SCReturn
Definition: util-debug.h:339
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
AppProto alproto
application level protocol
Definition: flow.h:409
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
int DecodeENIPPDU(uint8_t *input, uint32_t input_len, ENIPTransaction *enip_data)
Decode ENIP Encapsulation Header.
Flow data structure.
Definition: flow.h:325
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))