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"
22
23#include "lua.h"
24#include "lualib.h"
25#include "lauxlib.h"
26
27#include "util-lua.h"
28#include "util-lua-common.h"
29#include "util-lua-dnp3.h"
31
32/**
33 * \brief Helper macro to push key and integer value onto a table.
34 */
35#define LUA_PUSHT_INT(l, k, v) do { \
36 lua_pushliteral(luastate, k); \
37 lua_pushinteger(luastate, v); \
38 lua_settable(luastate, -3); \
39 } while (0);
40
41static void SCLuaPushTableBoolean(lua_State *L, const char *key, bool val)
42{
43 lua_pushstring(L, key);
44 lua_pushboolean(L, val);
45 lua_settable(L, -3);
46}
47
48static void DNP3PushPoints(lua_State *luastate, DNP3Object *object)
49{
50 DNP3Point *point;
51 int i = 1;
52
53 TAILQ_FOREACH(point, object->points, next) {
54 lua_pushinteger(luastate, i++);
55 lua_newtable(luastate);
56
57 lua_pushliteral(luastate, "index");
58 lua_pushinteger(luastate, point->index);
59 lua_settable(luastate, -3);
60
61 DNP3PushPoint(luastate, object, point);
62
63 lua_settable(luastate, -3);
64 }
65}
66
67static void DNP3PushObjects(lua_State *luastate, DNP3ObjectList *objects)
68{
69 DNP3Object *object = NULL;
70 int i = 1;
71
72 TAILQ_FOREACH(object, objects, next) {
73 lua_pushinteger(luastate, i++);
74 lua_newtable(luastate);
75
76 lua_pushliteral(luastate, "group");
77 lua_pushinteger(luastate, object->group);
78 lua_settable(luastate, -3);
79
80 lua_pushliteral(luastate, "variation");
81 lua_pushinteger(luastate, object->variation);
82 lua_settable(luastate, -3);
83
84 lua_pushliteral(luastate, "points");
85 lua_newtable(luastate);
86 DNP3PushPoints(luastate, object);
87 lua_settable(luastate, -3);
88
89 lua_settable(luastate, -3);
90 }
91}
92
93static void DNP3PushLinkHeader(lua_State *luastate, DNP3LinkHeader *header)
94{
95 LUA_PUSHT_INT(luastate, "len", header->len);
96 LUA_PUSHT_INT(luastate, "control", header->control);
97 LUA_PUSHT_INT(luastate, "dst", header->dst);
98 LUA_PUSHT_INT(luastate, "src", header->src);
99 LUA_PUSHT_INT(luastate, "crc", header->crc);
100}
101
102static void DNP3PushApplicationHeader(lua_State *luastate,
103 DNP3ApplicationHeader *header)
104{
105 LUA_PUSHT_INT(luastate, "control", header->control);
106 LUA_PUSHT_INT(luastate, "function_code", header->function_code);
107}
108
109static void DNP3PushRequest(lua_State *luastate, DNP3Transaction *tx)
110{
111 /* Link header. */
112 lua_pushliteral(luastate, "link_header");
113 lua_newtable(luastate);
114 DNP3PushLinkHeader(luastate, &tx->lh);
115 lua_settable(luastate, -3);
116
117 /* Transport header. */
118 LUA_PUSHT_INT(luastate, "transport_header", tx->th);
119
120 /* Application header. */
121 lua_pushliteral(luastate, "application_header");
122 lua_newtable(luastate);
123 DNP3PushApplicationHeader(luastate, &tx->ah);
124 lua_settable(luastate, -3);
125
126 lua_pushliteral(luastate, "objects");
127 lua_newtable(luastate);
128 DNP3PushObjects(luastate, &tx->objects);
129 lua_settable(luastate, -3);
130}
131
132static void DNP3PushResponse(lua_State *luastate, DNP3Transaction *tx)
133{
134 /* Link header. */
135 lua_pushliteral(luastate, "link_header");
136 lua_newtable(luastate);
137 DNP3PushLinkHeader(luastate, &tx->lh);
138 lua_settable(luastate, -3);
139
140 /* Transport header. */
141 LUA_PUSHT_INT(luastate, "transport_header", tx->th);
142
143 /* Application header. */
144 lua_pushliteral(luastate, "application_header");
145 lua_newtable(luastate);
146 DNP3PushApplicationHeader(luastate, &tx->ah);
147 lua_settable(luastate, -3);
148
149 /* Internal indicators. */
150 LUA_PUSHT_INT(luastate, "indicators", tx->iin.iin1 << 8 | tx->iin.iin2);
151
152 lua_pushliteral(luastate, "objects");
153 lua_newtable(luastate);
154 DNP3PushObjects(luastate, &tx->objects);
155 lua_settable(luastate, -3);
156}
157
158static int DNP3GetTx(lua_State *luastate)
159{
160 if (!LuaStateNeedProto(luastate, ALPROTO_DNP3)) {
161 return LuaCallbackError(luastate, "error: protocol not dnp3");
162 }
163
164 DNP3Transaction *tx = LuaStateGetTX(luastate);
165 if (tx == NULL) {
166 return LuaCallbackError(luastate, "error: no tx");
167 }
168
169 lua_newtable(luastate);
170
171 lua_pushliteral(luastate, "tx_num");
172 lua_pushinteger(luastate, tx->tx_num);
173 lua_settable(luastate, -3);
174
175 SCLuaPushTableBoolean(luastate, "is_request", tx->is_request);
176 if (tx->is_request) {
177 lua_pushliteral(luastate, "request");
178 lua_newtable(luastate);
179 SCLuaPushTableBoolean(luastate, "done", tx->done);
180 SCLuaPushTableBoolean(luastate, "complete", tx->complete);
181 DNP3PushRequest(luastate, tx);
182 lua_settable(luastate, -3);
183 } else {
184 lua_pushliteral(luastate, "response");
185 lua_newtable(luastate);
186 SCLuaPushTableBoolean(luastate, "done", tx->done);
187 SCLuaPushTableBoolean(luastate, "complete", tx->complete);
188 DNP3PushResponse(luastate, tx);
189 lua_settable(luastate, -3);
190 }
191
192 return 1;
193}
194
195static const struct luaL_Reg dnp3lib[] = {
196 // clang-format off
197 { "get_tx", DNP3GetTx, },
198 { NULL, NULL, }
199 // clang-format on
200};
201
203{
204 luaL_newlib(L, dnp3lib);
205 return 1;
206}
struct HtpBodyChunk_ * next
@ ALPROTO_DNP3
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
Struct to hold the list of decoded objects.
DNP3PointList * points
uint8_t variation
DNP3 object point.
uint32_t index
DNP3 transaction.
DNP3LinkHeader lh
DNP3InternalInd iin
DNP3TransportHeader th
DNP3ObjectList objects
DNP3ApplicationHeader ah
struct lua_State lua_State
int LuaStateNeedProto(lua_State *luastate, AppProto alproto)
int LuaCallbackError(lua_State *luastate, const char *msg)
void DNP3PushPoint(lua_State *luastate, DNP3Object *object, DNP3Point *point)
Push an object point item onto the stack.
#define LUA_PUSHT_INT(l, k, v)
Helper macro to push key and integer value onto a table.
int SCLuaLoadDnp3Lib(lua_State *L)
void * LuaStateGetTX(lua_State *luastate)
get tx pointer from the lua state
Definition util-lua.c:134