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