suricata
util-lua-dnp3.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 #include "suricata-common.h"
19 
20 #include "app-layer-dnp3.h"
21 #include "app-layer-dnp3-objects.h"
22 
23 #include "lua.h"
24 #include "lualib.h"
25 #include "lauxlib.h"
26 
27 #include "util-lua.h"
28 #include "util-lua-sandbox.h"
29 #include "util-lua-common.h"
30 #include "util-lua-dnp3.h"
31 #include "util-lua-dnp3-objects.h"
32 
33 /**
34  * \brief Helper macro to push key and integer value onto a table.
35  */
36 #define LUA_PUSHT_INT(l, k, v) do { \
37  lua_pushliteral(luastate, k); \
38  lua_pushinteger(luastate, v); \
39  lua_settable(luastate, -3); \
40  } while (0);
41 
42 static void SCLuaPushTableBoolean(lua_State *L, const char *key, bool val)
43 {
44  lua_pushstring(L, key);
45  lua_pushboolean(L, val);
46  lua_settable(L, -3);
47 }
48 
49 /*
50  * The per-object points value is either a plain array of copied point
51  * tables (point count up to DNP3_MAX_EAGER_POINTS) or, beyond that, a
52  * userdata object with __len and __index metamethods: materializing
53  * every point of a large response in get_tx() would exhaust the sandbox
54  * budget, failing the whole call with a memory limit error and
55  * silencing the rule. The userdata materializes an entry as a fresh
56  * table on each indexed access; # stays bounded by the cached count.
57  *
58  * The userdata stores no parser pointers in its ref: the object is
59  * re-derived from the resolved (flow, tx id) anchor on each cold
60  * indexed access, so a freed tx can never be followed. With the soft
61  * stale contract (9068) an index access after the tx is gone yields
62  * nil and # still reports the cached count. The other tx userdata
63  * raise on stale instead.
64  *
65  * A forward cursor caches (object, point, position) for the invocation
66  * that set it: a tx cannot be freed while a script call runs, so a
67  * matching (state, invocation generation) means the cached pointers are
68  * still live and points[i] is O(delta) instead of O(i) - without the
69  * cursor a numeric walk of n points costs n(n+1)/2 list steps.
70  */
71 #define DNP3_MAX_EAGER_POINTS 32
72 #define DNP3_POINTS_MT "sc.dnp3.points"
73 
74 typedef struct LuaDnp3Points_ {
75  SCLuaTxRef ref; /* (flow, tx id) anchor for the originating tx */
76  uint32_t object_idx; /* object position in the tx's objects list */
77  uint32_t n_points; /* count cached at creation */
78  /* forward cursor, trusted only for the invocation that set it */
79  uint64_t cursor_gen;
82  uint32_t cursor_pos; /* 1-based index of cursor_point; 0 = none */
83  /* pairs() walk cursor: own fields so a pairs() run and an __index
84  * walk cannot invalidate each other; seeded only on success */
85  uint64_t pairs_gen;
88  uint32_t pairs_pos; /* 1-based index of pairs_point; 0 = none */
90 
91 /* __len metamethod: argument 1 is the points userdata. Both
92  * metamethods check the tagged handle: in unsandboxed states a script
93  * can pull them off the metatable and call them with a foreign
94  * argument; a table or nil must error, not get dereferenced. */
95 static int Dnp3PointsLen(lua_State *luastate)
96 {
97  /* count cached at creation; the handle holds no parser pointers
98  * (the object is re-derived on index access), so no liveness
99  * check here: a stale handle still reports the count */
100  LuaDnp3Points *pts =
102  if (pts == NULL) {
103  return luaL_error(luastate, "invalid dnp3 points handle");
104  }
105  lua_pushinteger(luastate, pts->n_points);
106  return 1;
107 }
108 
109 /* __index metamethod: argument 1 is the points userdata, 2 the key */
110 static int Dnp3PointsIndex(lua_State *luastate)
111 {
112  /* plain type check: the cursor path below skips the resolve, and
113  * the cold path resolves explicitly (a stale tx then yields nil,
114  * the soft 9068 contract, without touching parser memory) */
115  LuaDnp3Points *pts =
117  if (pts == NULL) {
118  lua_pushnil(luastate);
119  return 1;
120  }
121  const lua_Integer i = lua_tointeger(luastate, 2);
122  /* bounds against the cached count also rejects indices past
123  * UINT32_MAX before any (uint32_t) cast */
124  if (i < 1 || (uint64_t)i > pts->n_points) {
125  lua_pushnil(luastate);
126  return 1;
127  }
128 
129  /* indices are 1-based */
130  DNP3Object *object;
131  DNP3Point *point;
132  uint32_t idx;
133  /* the generation is bumped once per invocation of this state, so a
134  * mismatch means the invocation that set the cursor is over (a tx
135  * can be evicted while its flow stays live); deinit() and close-time
136  * finalizers run without an invocation, so also require the
137  * invocation's flow to be the anchor flow (the registry flow is
138  * cleared before deinit); the nonzero test keeps a state without the
139  * slot from ever trusting the cursor */
140  if (pts->cursor_gen != 0 && LuaStateGetInvocationGen(luastate) == pts->cursor_gen &&
141  LuaStateGetFlow(luastate) == pts->ref.flow && pts->ref.flow != NULL &&
142  pts->cursor_pos >= 1) {
143  /* access at, ahead of, or behind the cursor in the invocation
144  * that set it: the tx cannot have been freed, so a same-position
145  * re-read is the cached point itself, a forward one continues
146  * from the cursor, and a backward one steps back through the
147  * TAILQ; monotone loops, either direction, stay O(n) */
148  object = pts->cursor_object;
149  point = pts->cursor_point;
150  idx = pts->cursor_pos;
151  while (idx < (uint32_t)i) {
152  point = point->next.tqe_next;
153  idx++;
154  if (point == NULL) {
155  break;
156  }
157  }
158  /* the bounds check above keeps i >= 1, so the walk-back cannot
159  * run past the first element (where TAILQ_PREV would wrap) */
160  while (idx > (uint32_t)i) {
161  point = TAILQ_PREV(point, DNP3PointList_, next);
162  idx--;
163  }
164  } else {
165  /* cold path: resolve the originating tx and re-derive the
166  * object from it: the ref stores only the object position, so
167  * a freed tx is never followed */
168  void *txptr = NULL;
169  if (!SCLuaTxRefResolve(luastate, &pts->ref, &txptr)) {
170  lua_pushnil(luastate);
171  return 1;
172  }
173  DNP3Transaction *tx = (DNP3Transaction *)txptr;
174  object = NULL;
175  uint32_t k = 0;
176  TAILQ_FOREACH (object, &tx->objects, next) {
177  if (k == pts->object_idx) {
178  break;
179  }
180  k++;
181  }
182  if (object == NULL || k != pts->object_idx) {
183  lua_pushnil(luastate);
184  return 1;
185  }
186  point = TAILQ_FIRST(object->points);
187  idx = 1;
188  while (point != NULL && idx < (uint32_t)i) {
189  point = point->next.tqe_next;
190  idx++;
191  }
192  if (point == NULL) {
193  lua_pushnil(luastate);
194  return 1;
195  }
196  }
197 
198  if (point == NULL) {
199  lua_pushnil(luastate);
200  return 1;
201  }
202 
203  lua_newtable(luastate);
204  lua_pushinteger(luastate, point->index);
205  lua_setfield(luastate, -2, "index");
206  DNP3PushPoint(luastate, object, point);
207  /* seed the cursor only on success: a cold-path overrun must not
208  * leave the generation current while point/pos still describe the
209  * previous invocation's point */
210  pts->cursor_gen = LuaStateGetInvocationGen(luastate);
211  pts->cursor_object = object;
212  pts->cursor_point = point;
213  pts->cursor_pos = idx;
214  return 1;
215 }
216 
217 /* __pairs generic iterator: arguments are the handle state and the last
218  * returned position (0 = start); returns (position, point table) or no
219  * values. Walks the resolved object's live list, so a freed tx or a
220  * vanished object ends the loop quietly, matching the stale index
221  * yielding nil. Straight-line runs continue from the pairs cursor (one
222  * hop per step, O(n) total); a jump into the captured iterator falls
223  * back to the cold walk. The cursor uses its own fields so it cannot
224  * disturb the __index cursor. */
225 static int Dnp3PointsNext(lua_State *luastate)
226 {
227  LuaDnp3Points *pts =
229  if (pts == NULL) {
230  return 0;
231  }
232  const lua_Integer pos = lua_tointeger(luastate, 2);
233  if (pos < 0 || (uint64_t)pos + 1 > pts->n_points) {
234  return 0;
235  }
236 
237  DNP3Object *object;
238  DNP3Point *point;
239  /* continuation of a pairs() run in the invocation that seeded the
240  * cursor: the control variable is exactly the position returned
241  * last, so one hop from the cursor is enough; a tx cannot be freed
242  * while the call runs */
243  if (pts->pairs_gen != 0 && LuaStateGetInvocationGen(luastate) == pts->pairs_gen &&
244  LuaStateGetFlow(luastate) == pts->ref.flow && pts->ref.flow != NULL && pos > 0 &&
245  (uint32_t)pos == pts->pairs_pos) {
246  object = pts->pairs_object;
247  point = pts->pairs_point->next.tqe_next;
248  } else {
249  /* cold path: resolve the originating tx and re-derive the
250  * object from it: the ref stores only the object position, so
251  * a freed tx is never followed */
252  void *txptr = NULL;
253  if (!SCLuaTxRefResolve(luastate, &pts->ref, &txptr)) {
254  return 0;
255  }
256  DNP3Transaction *tx = (DNP3Transaction *)txptr;
257  object = NULL;
258  uint32_t k = 0;
259  TAILQ_FOREACH (object, &tx->objects, next) {
260  if (k == pts->object_idx) {
261  break;
262  }
263  k++;
264  }
265  if (object == NULL || k != pts->object_idx) {
266  return 0;
267  }
268  point = TAILQ_FIRST(object->points);
269  uint32_t idx = 1;
270  while (point != NULL && idx <= (uint32_t)pos) {
271  point = point->next.tqe_next;
272  idx++;
273  }
274  }
275  if (point == NULL) {
276  return 0;
277  }
278 
279  /* generic-for contract: the first return value (second-lowest of
280  * the two) is the control variable, so the key goes down first
281  * and the point table on top; the shape matches the eager copy */
282  lua_pushinteger(luastate, pos + 1);
283  lua_newtable(luastate);
284  lua_pushinteger(luastate, point->index);
285  lua_setfield(luastate, -2, "index");
286  DNP3PushPoint(luastate, object, point);
287  /* seed the cursor only on success */
288  pts->pairs_gen = LuaStateGetInvocationGen(luastate);
289  pts->pairs_object = object;
290  pts->pairs_point = point;
291  pts->pairs_pos = (uint32_t)(pos + 1);
292  return 2;
293 }
294 
295 /* __pairs metamethod: pairs(obj.points) must walk the lazy value the
296  * same way the eager table is walked: (position, point table) for
297  * 1..n, nothing past n. Pre-threshold objects already behaved that
298  * way as plain tables, so scripts iterating pairs() keep working past
299  * the threshold too. */
300 static int Dnp3PointsPairs(lua_State *luastate)
301 {
302  LuaDnp3Points *pts =
304  if (pts == NULL) {
305  lua_pushnil(luastate);
306  return 1;
307  }
308  lua_pushcfunction(luastate, Dnp3PointsNext);
309  /* state: the handle; start before the first point */
310  lua_pushvalue(luastate, 1);
311  lua_pushinteger(luastate, 0);
312  return 3;
313 }
314 
315 static void DNP3PushObjectPoints(lua_State *luastate, DNP3Object *object, uint32_t object_idx)
316 {
317  DNP3Point *p;
318  uint32_t n = 0;
319  TAILQ_FOREACH (p, object->points, next) {
320  n++;
321  }
322 
323  if (n <= DNP3_MAX_EAGER_POINTS) {
324  /* small count: copy the points, the tables stay valid after the
325  * tx is gone */
326  lua_newtable(luastate);
327  uint32_t i = 0;
328  TAILQ_FOREACH (p, object->points, next) {
329  i++;
330  lua_pushinteger(luastate, i);
331  lua_newtable(luastate);
332  lua_pushinteger(luastate, p->index);
333  lua_setfield(luastate, -2, "index");
334  DNP3PushPoint(luastate, object, p);
335  lua_settable(luastate, -3);
336  }
337  return;
338  }
339 
340  LuaDnp3Points *pts =
341  (LuaDnp3Points *)SCLuaNewUserData(luastate, SCLUA_TUD_DNP3_POINTS, sizeof(*pts));
342  if (pts == NULL) {
343  /* defensive: lua_newuserdata raises on OOM; checked like
344  * the other SCLuaNewUserData call sites */
345  lua_pushnil(luastate);
346  return;
347  }
348  pts->object_idx = object_idx;
349  pts->n_points = n;
350  /* lua_newuserdata does not zero: start with no cursor and no
351  * pairs run, so the iterator fast path cannot see stale values */
352  pts->cursor_gen = 0;
353  pts->cursor_object = NULL;
354  pts->cursor_point = NULL;
355  pts->cursor_pos = 0;
356  pts->pairs_gen = 0;
357  pts->pairs_object = NULL;
358  pts->pairs_point = NULL;
359  pts->pairs_pos = 0;
360  SCLuaTxRefInit(luastate, &pts->ref, LuaStateGetTxId(luastate));
361  /* stack: [.., obj_t, "points", ud] */
362 
363  if (luaL_newmetatable(luastate, DNP3_POINTS_MT)) {
364  /* stack: [.., ud, mt]: fill once, on first use */
365  lua_pushliteral(luastate, "__index");
366  lua_pushcfunction(luastate, Dnp3PointsIndex);
367  lua_settable(luastate, -3);
368  lua_pushliteral(luastate, "__len");
369  lua_pushcfunction(luastate, Dnp3PointsLen);
370  lua_settable(luastate, -3);
371  lua_pushliteral(luastate, "__pairs");
372  lua_pushcfunction(luastate, Dnp3PointsPairs);
373  lua_settable(luastate, -3);
374  }
375  /* stack: [.., obj_t, "points", ud, mt] */
376  /* pops the mt, tags the userdata: ud becomes the top again */
377  lua_setmetatable(luastate, -2);
378  /* stack: [.., obj_t, "points", ud]: caller's settable sees ud */
379 }
380 
381 static void DNP3PushObjects(lua_State *luastate, DNP3ObjectList *objects)
382 {
383  DNP3Object *object = NULL;
384  int i = 1;
385  uint32_t obj_idx = 0;
386 
387  TAILQ_FOREACH(object, objects, next) {
388  lua_pushinteger(luastate, i++);
389  lua_newtable(luastate);
390 
391  lua_pushliteral(luastate, "group");
392  lua_pushinteger(luastate, object->group);
393  lua_settable(luastate, -3);
394 
395  lua_pushliteral(luastate, "variation");
396  lua_pushinteger(luastate, object->variation);
397  lua_settable(luastate, -3);
398 
399  lua_pushliteral(luastate, "points");
400  DNP3PushObjectPoints(luastate, object, obj_idx++);
401  lua_settable(luastate, -3);
402 
403  lua_settable(luastate, -3);
404  }
405 }
406 
407 static void DNP3PushLinkHeader(lua_State *luastate, DNP3LinkHeader *header)
408 {
409  LUA_PUSHT_INT(luastate, "len", header->len);
410  LUA_PUSHT_INT(luastate, "control", header->control);
411  LUA_PUSHT_INT(luastate, "dst", header->dst);
412  LUA_PUSHT_INT(luastate, "src", header->src);
413  LUA_PUSHT_INT(luastate, "crc", header->crc);
414 }
415 
416 static void DNP3PushApplicationHeader(lua_State *luastate,
417  DNP3ApplicationHeader *header)
418 {
419  LUA_PUSHT_INT(luastate, "control", header->control);
420  LUA_PUSHT_INT(luastate, "function_code", header->function_code);
421 }
422 
423 static void DNP3PushRequest(lua_State *luastate, DNP3Transaction *tx)
424 {
425  /* Link header. */
426  lua_pushliteral(luastate, "link_header");
427  lua_newtable(luastate);
428  DNP3PushLinkHeader(luastate, &tx->lh);
429  lua_settable(luastate, -3);
430 
431  /* Transport header. */
432  LUA_PUSHT_INT(luastate, "transport_header", tx->th);
433 
434  /* Application header. */
435  lua_pushliteral(luastate, "application_header");
436  lua_newtable(luastate);
437  DNP3PushApplicationHeader(luastate, &tx->ah);
438  lua_settable(luastate, -3);
439 
440  lua_pushliteral(luastate, "objects");
441  lua_newtable(luastate);
442  DNP3PushObjects(luastate, &tx->objects);
443  lua_settable(luastate, -3);
444 }
445 
446 static void DNP3PushResponse(lua_State *luastate, DNP3Transaction *tx)
447 {
448  /* Link header. */
449  lua_pushliteral(luastate, "link_header");
450  lua_newtable(luastate);
451  DNP3PushLinkHeader(luastate, &tx->lh);
452  lua_settable(luastate, -3);
453 
454  /* Transport header. */
455  LUA_PUSHT_INT(luastate, "transport_header", tx->th);
456 
457  /* Application header. */
458  lua_pushliteral(luastate, "application_header");
459  lua_newtable(luastate);
460  DNP3PushApplicationHeader(luastate, &tx->ah);
461  lua_settable(luastate, -3);
462 
463  /* Internal indicators. */
464  LUA_PUSHT_INT(luastate, "indicators", tx->iin.iin1 << 8 | tx->iin.iin2);
465 
466  lua_pushliteral(luastate, "objects");
467  lua_newtable(luastate);
468  DNP3PushObjects(luastate, &tx->objects);
469  lua_settable(luastate, -3);
470 }
471 
472 static int DNP3GetTx(lua_State *luastate)
473 {
474  if (!LuaStateNeedProto(luastate, ALPROTO_DNP3)) {
475  return LuaCallbackError(luastate, "error: protocol not dnp3");
476  }
477 
478  DNP3Transaction *tx = LuaStateGetTX(luastate);
479  if (tx == NULL) {
480  return LuaCallbackError(luastate, "error: no tx");
481  }
482 
483  lua_newtable(luastate);
484 
485  lua_pushliteral(luastate, "tx_num");
486  lua_pushinteger(luastate, tx->tx_num);
487  lua_settable(luastate, -3);
488 
489  SCLuaPushTableBoolean(luastate, "is_request", tx->is_request);
490  if (tx->is_request) {
491  lua_pushliteral(luastate, "request");
492  lua_newtable(luastate);
493  SCLuaPushTableBoolean(luastate, "done", tx->done);
494  SCLuaPushTableBoolean(luastate, "complete", tx->complete);
495  DNP3PushRequest(luastate, tx);
496  lua_settable(luastate, -3);
497  } else {
498  lua_pushliteral(luastate, "response");
499  lua_newtable(luastate);
500  SCLuaPushTableBoolean(luastate, "done", tx->done);
501  SCLuaPushTableBoolean(luastate, "complete", tx->complete);
502  DNP3PushResponse(luastate, tx);
503  lua_settable(luastate, -3);
504  }
505 
506  return 1;
507 }
508 
509 static const struct luaL_Reg dnp3lib[] = {
510  // clang-format off
511  { "get_tx", DNP3GetTx, },
512  { NULL, NULL, }
513  // clang-format on
514 };
515 
517 {
518  luaL_newlib(L, dnp3lib);
519  return 1;
520 }
LuaDnp3Points_::n_points
uint32_t n_points
Definition: util-lua-dnp3.c:77
DNP3Transaction_::complete
uint8_t complete
Definition: app-layer-dnp3.h:231
LuaDnp3Points_::cursor_point
DNP3Point * cursor_point
Definition: util-lua-dnp3.c:81
LuaDnp3Points_::cursor_gen
uint64_t cursor_gen
Definition: util-lua-dnp3.c:79
util-lua-common.h
TAILQ_PREV
#define TAILQ_PREV(elm, headname, field)
Definition: queue.h:309
LuaDnp3Points_::cursor_pos
uint32_t cursor_pos
Definition: util-lua-dnp3.c:82
DNP3Transaction_::done
uint8_t done
Definition: app-layer-dnp3.h:230
DNP3Transaction_::th
DNP3TransportHeader th
Definition: app-layer-dnp3.h:227
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
util-lua.h
DNP3Object_
Struct to hold the list of decoded objects.
Definition: app-layer-dnp3.h:196
LuaCallbackError
int LuaCallbackError(lua_State *luastate, const char *msg)
Definition: util-lua-common.c:218
SCLuaTxRef_
Definition: util-lua-common.h:92
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
DNP3Transaction_::objects
DNP3ObjectList objects
Definition: app-layer-dnp3.h:225
p
Packet * p
Definition: fuzz_dataset.c:30
LUA_PUSHT_INT
#define LUA_PUSHT_INT(l, k, v)
Helper macro to push key and integer value onto a table.
Definition: util-lua-dnp3.c:36
lua_State
struct lua_State lua_State
Definition: suricata-common.h:527
LuaDnp3Points_::pairs_point
DNP3Point * pairs_point
Definition: util-lua-dnp3.c:87
DNP3Object_::points
DNP3PointList * points
Definition: app-layer-dnp3.h:205
SCLUA_TUD_DNP3_POINTS
@ SCLUA_TUD_DNP3_POINTS
Definition: util-lua-common.h:68
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:250
DNP3Transaction_::ah
DNP3ApplicationHeader ah
Definition: app-layer-dnp3.h:228
SCLuaTxRefResolve
int SCLuaTxRefResolve(lua_State *L, const SCLuaTxRef *ref, void **tx)
Definition: util-lua-common.c:182
SCLuaLoadDnp3Lib
int SCLuaLoadDnp3Lib(lua_State *L)
Definition: util-lua-dnp3.c:516
DNP3Transaction_::iin
DNP3InternalInd iin
Definition: app-layer-dnp3.h:229
ALPROTO_DNP3
@ ALPROTO_DNP3
Definition: app-layer-protos.h:50
app-layer-dnp3.h
DNP3PushPoint
void DNP3PushPoint(lua_State *luastate, DNP3Object *object, DNP3Point *point)
Push an object point item onto the stack.
Definition: util-lua-dnp3-objects.c:40
LuaDnp3Points_::object_idx
uint32_t object_idx
Definition: util-lua-dnp3.c:76
SCLuaTxRef_::flow
struct Flow_ * flow
Definition: util-lua-common.h:93
util-lua-dnp3-objects.h
DNP3Object_::group
uint8_t group
Definition: app-layer-dnp3.h:197
LuaDnp3Points_
Definition: util-lua-dnp3.c:74
util-lua-dnp3.h
LuaDnp3Points_::pairs_pos
uint32_t pairs_pos
Definition: util-lua-dnp3.c:88
LuaDnp3Points_::cursor_object
DNP3Object * cursor_object
Definition: util-lua-dnp3.c:80
SCLuaNewUserData
void * SCLuaNewUserData(lua_State *L, uint32_t type_id, size_t size)
Definition: util-lua-common.c:42
util-lua-sandbox.h
DNP3Transaction_::is_request
bool is_request
Definition: app-layer-dnp3.h:219
LuaStateGetTX
void * LuaStateGetTX(lua_State *luastate)
get tx pointer from the lua state
Definition: util-lua.c:234
LuaStateGetTxId
uint64_t LuaStateGetTxId(lua_State *luastate)
get tx id from the lua state
Definition: util-lua.c:240
DNP3_MAX_EAGER_POINTS
#define DNP3_MAX_EAGER_POINTS
Definition: util-lua-dnp3.c:71
suricata-common.h
DNP3Transaction_::tx_num
uint64_t tx_num
Definition: app-layer-dnp3.h:218
DNP3Object_::variation
uint8_t variation
Definition: app-layer-dnp3.h:198
LuaDnp3Points
struct LuaDnp3Points_ LuaDnp3Points
LuaStateGetFlow
Flow * LuaStateGetFlow(lua_State *luastate)
get flow pointer from lua state
Definition: util-lua.c:260
LuaDnp3Points_::ref
SCLuaTxRef ref
Definition: util-lua-dnp3.c:75
DNP3Point_::index
uint32_t index
Definition: app-layer-dnp3.h:181
LuaDnp3Points_::pairs_gen
uint64_t pairs_gen
Definition: util-lua-dnp3.c:85
SCLuaTxRefInit
void SCLuaTxRefInit(lua_State *L, SCLuaTxRef *ref, uint64_t tx_id)
Definition: util-lua-common.c:164
app-layer-dnp3-objects.h
DNP3Transaction_::lh
DNP3LinkHeader lh
Definition: app-layer-dnp3.h:226
LuaStateGetInvocationGen
uint64_t LuaStateGetInvocationGen(lua_State *luastate)
get the current invocation generation for this state
Definition: util-lua.c:216
DNP3_POINTS_MT
#define DNP3_POINTS_MT
Definition: util-lua-dnp3.c:72
LuaStateNeedProto
int LuaStateNeedProto(lua_State *luastate, AppProto alproto)
Definition: util-lua-common.c:289
SCLuaCheckUserDataPayload
void * SCLuaCheckUserDataPayload(lua_State *L, int idx, const char *mt, uint32_t type_id)
Definition: util-lua-common.c:137
DNP3Point_
DNP3 object point.
Definition: app-layer-dnp3.h:179
DNP3Transaction_
DNP3 transaction.
Definition: app-layer-dnp3.h:215
LuaDnp3Points_::pairs_object
DNP3Object * pairs_object
Definition: util-lua-dnp3.c:86