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 *tx)
116 {
117  return ((ENIPTransaction *)tx)->decoder_events;
118 }
119 
120 static int ENIPStateGetEventInfo(const char *event_name, int *event_id, AppLayerEventType *event_type)
121 {
122  *event_id = SCMapEnumNameToValue(event_name, enip_decoder_event_table);
123 
124  if (*event_id == -1) {
125  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
126  "enip's enum map table.", event_name);
127  /* yes this is fatal */
128  return -1;
129  }
130 
131  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
132 
133  return 0;
134 }
135 
136 static int ENIPStateGetEventInfoById(int event_id, const char **event_name,
138 {
139  *event_name = SCMapEnumValueToName(event_id, enip_decoder_event_table);
140  if (*event_name == NULL) {
141  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%d\" not present in "
142  "enip's enum map table.", event_id);
143  /* yes this is fatal */
144  return -1;
145  }
146 
147  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
148 
149  return 0;
150 }
151 
152 /** \brief Allocate enip state
153  *
154  * return state
155  */
156 static void *ENIPStateAlloc(void)
157 {
158  SCLogDebug("ENIPStateAlloc");
159  void *s = SCMalloc(sizeof(ENIPState));
160  if (unlikely(s == NULL))
161  return NULL;
162 
163  memset(s, 0, sizeof(ENIPState));
164 
165  ENIPState *enip_state = (ENIPState *) s;
166 
167  TAILQ_INIT(&enip_state->tx_list);
168  return s;
169 }
170 
171 /** \internal
172  * \brief Free a ENIP TX
173  * \param tx ENIP TX to free */
174 static void ENIPTransactionFree(ENIPTransaction *tx, ENIPState *state)
175 {
176  SCEnter();
177  SCLogDebug("ENIPTransactionFree");
178  CIPServiceEntry *svc = NULL;
179  while ((svc = TAILQ_FIRST(&tx->service_list)))
180  {
181  TAILQ_REMOVE(&tx->service_list, svc, next);
182 
183  SegmentEntry *seg = NULL;
184  while ((seg = TAILQ_FIRST(&svc->segment_list)))
185  {
186  TAILQ_REMOVE(&svc->segment_list, seg, next);
187  SCFree(seg);
188  }
189 
190  AttributeEntry *attr = NULL;
191  while ((attr = TAILQ_FIRST(&svc->attrib_list)))
192  {
193  TAILQ_REMOVE(&svc->attrib_list, attr, next);
194  SCFree(attr);
195  }
196 
197  SCFree(svc);
198  }
199 
201 
202  if (tx->de_state != NULL)
203  {
205 
206  state->tx_with_detect_state_cnt--;
207  }
208 
209  if (state->iter == tx)
210  state->iter = NULL;
211 
212  SCFree(tx);
213  SCReturn;
214 }
215 
216 /** \brief Free enip state
217  *
218  */
219 static void ENIPStateFree(void *s)
220 {
221  SCEnter();
222  SCLogDebug("ENIPStateFree");
223  if (s)
224  {
225  ENIPState *enip_state = (ENIPState *) s;
226 
227  ENIPTransaction *tx = NULL;
228  while ((tx = TAILQ_FIRST(&enip_state->tx_list)))
229  {
230  TAILQ_REMOVE(&enip_state->tx_list, tx, next);
231  ENIPTransactionFree(tx, enip_state);
232  }
233 
234  if (enip_state->buffer != NULL)
235  {
236  SCFree(enip_state->buffer);
237  }
238 
239  SCFree(s);
240  }
241  SCReturn;
242 }
243 
244 /** \internal
245  * \brief Allocate a ENIP TX
246  * \retval tx or NULL */
247 static ENIPTransaction *ENIPTransactionAlloc(ENIPState *state)
248 {
249  SCLogDebug("ENIPStateTransactionAlloc");
251  sizeof(ENIPTransaction));
252  if (unlikely(tx == NULL))
253  return NULL;
254 
255  state->curr = tx;
256  state->transaction_max++;
257 
258  memset(tx, 0x00, sizeof(ENIPTransaction));
259  TAILQ_INIT(&tx->service_list);
260 
261  tx->enip = state;
262  tx->tx_num = state->transaction_max;
263  tx->service_count = 0;
264 
265  TAILQ_INSERT_TAIL(&state->tx_list, tx, next);
266 
267  return tx;
268 }
269 
270 /**
271  * \brief enip transaction cleanup callback
272  */
273 static void ENIPStateTransactionFree(void *state, uint64_t tx_id)
274 {
275  SCEnter();
276  SCLogDebug("ENIPStateTransactionFree");
277  ENIPState *enip_state = state;
278  ENIPTransaction *tx = NULL;
279  TAILQ_FOREACH(tx, &enip_state->tx_list, next)
280  {
281 
282  if ((tx_id+1) < tx->tx_num)
283  break;
284  else if ((tx_id+1) > tx->tx_num)
285  continue;
286 
287  if (tx == enip_state->curr)
288  enip_state->curr = NULL;
289 
290  if (tx->decoder_events != NULL)
291  {
292  if (tx->decoder_events->cnt <= enip_state->events)
293  enip_state->events -= tx->decoder_events->cnt;
294  else
295  enip_state->events = 0;
296  }
297 
298  TAILQ_REMOVE(&enip_state->tx_list, tx, next);
299  ENIPTransactionFree(tx, state);
300  break;
301  }
302  SCReturn;
303 }
304 
305 /** \internal
306  *
307  * \brief This function is called to retrieve a ENIP
308  *
309  * \param state ENIP state structure for the parser
310  * \param input Input line of the command
311  * \param input_len Length of the request
312  *
313  * \retval 1 when the command is parsed, 0 otherwise
314  */
315 static int ENIPParse(Flow *f, void *state, AppLayerParserState *pstate,
316  const uint8_t *input, uint32_t input_len, void *local_data,
317  const uint8_t flags)
318 {
319  SCEnter();
320  ENIPState *enip = (ENIPState *) state;
321  ENIPTransaction *tx;
322 
323  if (input == NULL && AppLayerParserStateIssetFlag(pstate,
325  {
326  SCReturnInt(1);
327  } else if (input == NULL && input_len != 0) {
328  // GAP
329  SCReturnInt(0);
330  } else if (input == NULL || input_len == 0)
331  {
332  SCReturnInt(-1);
333  }
334 
335  while (input_len > 0)
336  {
337  tx = ENIPTransactionAlloc(enip);
338  if (tx == NULL)
339  SCReturnInt(0);
340 
341  SCLogDebug("ENIPParse input len %d", input_len);
342  DecodeENIPPDU(input, input_len, tx);
343  uint32_t pkt_len = tx->header.length + sizeof(ENIPEncapHdr);
344  SCLogDebug("ENIPParse packet len %d", pkt_len);
345  if (pkt_len > input_len)
346  {
347  SCLogDebug("Invalid packet length");
348  break;
349  }
350 
351  input += pkt_len;
352  input_len -= pkt_len;
353  //SCLogDebug("remaining %d", input_len);
354 
355  if (input_len < sizeof(ENIPEncapHdr))
356  {
357  //SCLogDebug("Not enough data"); //not enough data for ENIP
358  break;
359  }
360  }
361 
362  return 1;
363 }
364 
365 
366 
367 static uint16_t ENIPProbingParser(Flow *f, uint8_t direction,
368  const uint8_t *input, uint32_t input_len, uint8_t *rdir)
369 {
370  // SCLogDebug("ENIPProbingParser %d", input_len);
371  if (input_len < sizeof(ENIPEncapHdr))
372  {
373  SCLogDebug("length too small to be a ENIP header");
374  return ALPROTO_UNKNOWN;
375  }
376 
377  return ALPROTO_ENIP;
378 }
379 
380 /**
381  * \brief Function to register the ENIP protocol parsers and other functions
382  */
384 {
385  SCEnter();
386  const char *proto_name = "enip";
387 
388  if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name))
389  {
391 
392  if (RunmodeIsUnittests())
393  {
394  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818", ALPROTO_ENIP,
395  0, sizeof(ENIPEncapHdr), STREAM_TOSERVER, ENIPProbingParser, NULL);
396 
397  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818", ALPROTO_ENIP,
398  0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT, ENIPProbingParser, NULL);
399 
400  } else
401  {
402  if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
403  proto_name, ALPROTO_ENIP, 0, sizeof(ENIPEncapHdr),
404  ENIPProbingParser, ENIPProbingParser))
405  {
406  SCLogDebug(
407  "no ENIP UDP config found enabling ENIP detection on port 44818.");
408 
409  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818",
411  ENIPProbingParser, NULL);
412 
413  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818",
415  ENIPProbingParser, NULL);
416  }
417  }
418 
419  } else
420  {
421  SCLogConfig("Protocol detection and parser disabled for %s protocol.",
422  proto_name);
423  return;
424  }
425 
426  if (AppLayerParserConfParserEnabled("udp", proto_name))
427  {
429  STREAM_TOSERVER, ENIPParse);
431  STREAM_TOCLIENT, ENIPParse);
432 
434  ENIPStateAlloc, ENIPStateFree);
435 
436  AppLayerParserRegisterGetEventsFunc(IPPROTO_UDP, ALPROTO_ENIP, ENIPGetEvents);
437 
439  ENIPGetTxDetectState, ENIPSetTxDetectState);
440 
441  AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_ENIP, ENIPGetTx);
442  AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_ENIP, ENIPGetTxCnt);
443  AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_ENIP, ENIPStateTransactionFree);
444 
445  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_UDP, ALPROTO_ENIP, ENIPGetAlstateProgress);
446  AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_ENIP, ENIPGetAlstateProgressCompletionStatus);
447 
448  AppLayerParserRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_ENIP, ENIPStateGetEventInfo);
449  AppLayerParserRegisterGetEventInfoById(IPPROTO_UDP, ALPROTO_ENIP, ENIPStateGetEventInfoById);
450 
453 
454  } else
455  {
456  SCLogInfo(
457  "Parsed disabled for %s protocol. Protocol detection" "still on.",
458  proto_name);
459  }
460 
461 #ifdef UNITTESTS
463 #endif
464 
465  SCReturn;
466 }
467 
468 /**
469  * \brief Function to register the ENIP protocol parsers and other functions
470  */
472 {
473  SCEnter();
474  const char *proto_name = "enip";
475 
476  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name))
477  {
479 
480  if (RunmodeIsUnittests())
481  {
482  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "44818", ALPROTO_ENIP,
483  0, sizeof(ENIPEncapHdr), STREAM_TOSERVER, ENIPProbingParser, NULL);
484 
485  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "44818", ALPROTO_ENIP,
486  0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT, ENIPProbingParser, NULL);
487 
488  } else
489  {
490  if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
491  proto_name, ALPROTO_ENIP, 0, sizeof(ENIPEncapHdr),
492  ENIPProbingParser, ENIPProbingParser))
493  {
494 #ifndef AFLFUZZ_APPLAYER
495  return;
496 #endif
497  }
498  }
499 
500  } else
501  {
502  SCLogDebug("Protocol detection and parser disabled for %s protocol.",
503  proto_name);
504  return;
505  }
506 
507  if (AppLayerParserConfParserEnabled("tcp", proto_name))
508  {
510  STREAM_TOSERVER, ENIPParse);
512  STREAM_TOCLIENT, ENIPParse);
514  ENIPStateAlloc, ENIPStateFree);
515 
516  AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_ENIP, ENIPGetEvents);
517 
519  ENIPGetTxDetectState, ENIPSetTxDetectState);
520 
521  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_ENIP, ENIPGetTx);
522  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_ENIP, ENIPGetTxCnt);
523  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_ENIP, ENIPStateTransactionFree);
524 
525  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_ENIP, ENIPGetAlstateProgress);
526  AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_ENIP, ENIPGetAlstateProgressCompletionStatus);
527 
528  AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_ENIP, ENIPStateGetEventInfo);
529 
532 
533  /* This parser accepts gaps. */
536 
537  } else
538  {
539  SCLogConfig("Parser disabled for %s protocol. Protocol detection still on.",
540  proto_name);
541  }
542 
543 #ifdef UNITTESTS
545 #endif
546 
547  SCReturn;
548 }
549 
550 /* UNITTESTS */
551 #ifdef UNITTESTS
552 #include "app-layer-parser.h"
553 #include "detect-parse.h"
554 #include "detect-engine.h"
555 #include "flow-util.h"
556 #include "stream-tcp.h"
557 #include "util-unittest.h"
558 #include "util-unittest-helper.h"
559 
560 static uint8_t listIdentity[] = {/* List ID */ 0x63, 0x00,
561  /* Length */ 0x00, 0x00,
562  /* Session */ 0x00, 0x00, 0x00, 0x00,
563  /* Status */ 0x00, 0x00, 0x00, 0x00,
564  /* Delay*/ 0x00,
565  /* Context */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566  /* Quantity of coils */ 0x00, 0x00, 0x00, 0x00, 0x00};
567 
568 /**
569  * \brief Test if ENIP Packet matches signature
570  */
571 static int ALDecodeENIPTest(void)
572 {
574  Flow f;
575  TcpSession ssn;
576 
577  memset(&f, 0, sizeof(f));
578  memset(&ssn, 0, sizeof(ssn));
579 
580  f.protoctx = (void *)&ssn;
581  f.proto = IPPROTO_TCP;
582  f.alproto = ALPROTO_ENIP;
583 
585 
586  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_ENIP, STREAM_TOSERVER,
587  listIdentity, sizeof(listIdentity));
588  FAIL_IF(r != 0);
589 
590  ENIPState *enip_state = f.alstate;
591  FAIL_IF_NULL(enip_state);
592 
593  ENIPTransaction *tx = ENIPGetTx(enip_state, 0);
594  FAIL_IF_NULL(tx);
595 
596  FAIL_IF(tx->header.command != 99);
597 
598  AppLayerParserThreadCtxFree(alp_tctx);
600  FLOW_DESTROY(&f);
601 
602  PASS;
603 }
604 
605 #endif /* UNITTESTS */
606 
608 {
609 #ifdef UNITTESTS
610  UtRegisterTest("ALDecodeENIPTest", ALDecodeENIPTest);
611 #endif /* UNITTESTS */
612 }
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)
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
Definition: util-enum.c:69
#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
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *))
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:253
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:121
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:267
#define SCReturnInt(x)
Definition: util-debug.h:341
void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfoById)(int event_id, const char **event_name, AppLayerEventType *event_type))
#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:222
int DecodeENIPPDU(const uint8_t *input, uint32_t input_len, ENIPTransaction *enip_data)
Decode ENIP Encapsulation Header.
#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:322
uint16_t tx_id
AppLayerDecoderEvents * decoder_events
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
#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.
Flow data structure.
Definition: flow.h:325
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))