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