]> git.ipfire.org Git - people/ms/suricata.git/blame - scripts/dnp3-gen/dnp3-gen.py
jansson: remove HAVE_LIBJANSSON guards
[people/ms/suricata.git] / scripts / dnp3-gen / dnp3-gen.py
CommitLineData
240d789c
JI
1#! /usr/bin/env python
2#
3# Copyright (C) 2015 Open Information Security Foundation
4#
5# You can copy, redistribute or modify this Program under the terms of
6# the GNU General Public License version 2 as published by the Free
7# Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# version 2 along with this program; if not, write to the Free Software
16# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17# 02110-1301, USA.
18
19# This script generates DNP3 related source code based on definitions
20# of DNP3 objects (currently the object structs).
21
22from __future__ import print_function
23
24import sys
25import re
26from cStringIO import StringIO
27import yaml
28import types
29
30import jinja2
31
32IN_PLACE_START = "/* START GENERATED CODE */"
33IN_PLACE_END = "/* END GENERATED CODE */"
34
35util_lua_dnp3_objects_c_template = """/* Copyright (C) 2015 Open Information Security Foundation
36 *
37 * You can copy, redistribute or modify this Program under the terms of
38 * the GNU General Public License version 2 as published by the Free
39 * Software Foundation.
40 *
41 * This program is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 * GNU General Public License for more details.
45 *
46 * You should have received a copy of the GNU General Public License
47 * version 2 along with this program; if not, write to the Free Software
48 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
49 * 02110-1301, USA.
50 */
51
52/**
53 * DO NOT EDIT. THIS FILE IS AUTO-GENERATED.
54 *
55 * Generated by command:
56 * {{command_line}}
57 */
58
59#include "suricata-common.h"
60
61#include "app-layer-dnp3.h"
62#include "app-layer-dnp3-objects.h"
63
64#ifdef HAVE_LUA
65
66#include <lua.h>
67#include <lualib.h>
68#include <lauxlib.h>
69
70#include "util-lua.h"
ac7cf48a 71#include "util-lua-dnp3-objects.h"
240d789c
JI
72
73/**
74 * \\brief Push an object point item onto the stack.
75 */
76void DNP3PushPoint(lua_State *luastate, DNP3Object *object,
77 DNP3Point *point)
78{
79 switch (DNP3_OBJECT_CODE(object->group, object->variation)) {
80{% for object in objects %}
81 case DNP3_OBJECT_CODE({{object.group}}, {{object.variation}}): {
82 DNP3ObjectG{{object.group}}V{{object.variation}} *data = point->data;
83{% for field in object.fields %}
84{% if is_integer_type(field.type) %}
85 lua_pushliteral(luastate, "{{field.name}}");
86 lua_pushinteger(luastate, data->{{field.name}});
87 lua_settable(luastate, -3);
88{% elif field["type"] in ["flt32", "flt64"] %}
89 lua_pushliteral(luastate, "{{field.name}}");
90 lua_pushnumber(luastate, data->{{field.name}});
91 lua_settable(luastate, -3);
92{% elif field["type"] == "chararray" %}
93 lua_pushliteral(luastate, "{{field.name}}");
94 LuaPushStringBuffer(luastate, (uint8_t *)data->{{field.name}},
95 strlen(data->{{field.name}}));
96 lua_settable(luastate, -3);
97{% elif field["type"] == "vstr4" %}
98 lua_pushliteral(luastate, "{{field.name}}");
99 LuaPushStringBuffer(luastate, (uint8_t *)data->{{field.name}},
100 strlen(data->{{field.name}}));
101 lua_settable(luastate, -3);
102{% elif field.type == "bytearray" %}
103 lua_pushliteral(luastate, "{{field.name}}");
104 lua_pushlstring(luastate, (const char *)data->{{field.name}},
105 data->{{field.len_field}});
106 lua_settable(luastate, -3);
107{% elif field.type == "bstr8" %}
108{% for field in field.fields %}
109 lua_pushliteral(luastate, "{{field.name}}");
110 lua_pushinteger(luastate, data->{{field.name}});
111 lua_settable(luastate, -3);
112{% endfor %}
113{% else %}
114{{ raise("Unhandled datatype: %s" % (field.type)) }}
115{% endif %}
116{% endfor %}
117 break;
118 }
119{% endfor %}
120 default:
121 break;
122 }
123}
124
125#endif /* HAVE_LUA */
126
127"""
128
129output_json_dnp3_objects_template = """/* Copyright (C) 2015 Open Information Security Foundation
130 *
131 * You can copy, redistribute or modify this Program under the terms of
132 * the GNU General Public License version 2 as published by the Free
133 * Software Foundation.
134 *
135 * This program is distributed in the hope that it will be useful,
136 * but WITHOUT ANY WARRANTY; without even the implied warranty of
137 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138 * GNU General Public License for more details.
139 *
140 * You should have received a copy of the GNU General Public License
141 * version 2 along with this program; if not, write to the Free Software
142 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
143 * 02110-1301, USA.
144 */
145
146/**
147 * DO NOT EDIT. THIS FILE IS AUTO-GENERATED.
148 *
149 * Generated by command:
150 * {{command_line}}
151 */
152
153#include "suricata-common.h"
154
155#include "util-crypt.h"
156
157#include "app-layer-dnp3.h"
158#include "app-layer-dnp3-objects.h"
ac7cf48a 159#include "output-json-dnp3-objects.h"
240d789c 160
240d789c
JI
161void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object,
162 DNP3Point *point)
163{
164
165 switch (DNP3_OBJECT_CODE(object->group, object->variation)) {
166{% for object in objects %}
167 case DNP3_OBJECT_CODE({{object.group}}, {{object.variation}}): {
168 DNP3ObjectG{{object.group}}V{{object.variation}} *data = point->data;
169{% for field in object.fields %}
170{% if is_integer_type(field.type) %}
171 json_object_set_new(js, "{{field.name}}",
172 json_integer(data->{{field.name}}));
173{% elif field.type in ["flt32", "flt64"] %}
174 json_object_set_new(js, "{{field.name}}",
175 json_real(data->{{field.name}}));
176{% elif field.type == "bytearray" %}
177 unsigned long {{field.name}}_b64_len = data->{{field.len_field}} * 2;
178 uint8_t {{field.name}}_b64[{{field.name}}_b64_len];
179 Base64Encode(data->{{field.name}}, data->{{field.len_field}},
180 {{field.name}}_b64, &{{field.name}}_b64_len);
181 json_object_set_new(js, "data->{{field.name}}",
182 json_string((char *){{field.name}}_b64));
183{% elif field.type == "vstr4" %}
184 json_object_set_new(js, "data->{{field.name}}", json_string(data->{{field.name}}));
185{% elif field.type == "chararray" %}
186 if (data->{{field.len_field}} > 0) {
187 /* First create a null terminated string as not all versions
188 * of jansson have json_stringn. */
189 char tmpbuf[data->{{field.len_field}} + 1];
190 memcpy(tmpbuf, data->{{field.name}}, data->{{field.len_field}});
191 tmpbuf[data->{{field.len_field}}] = '\\0';
192 json_object_set_new(js, "{{field.name}}", json_string(tmpbuf));
193 } else {
194 json_object_set_new(js, "{{field.name}}", json_string(""));
195 }
196{% elif field.type == "bstr8" %}
197{% for field in field.fields %}
198 json_object_set_new(js, "{{field.name}}",
199 json_integer(data->{{field.name}}));
200{% endfor %}
201{% else %}
202{{ raise("Unhandled datatype: %s" % (field.type)) }}
203{% endif %}
204{% endfor %}
205 break;
206 }
207{% endfor %}
208 default:
209 SCLogDebug("Unknown object: %d:%d", object->group,
210 object->variation);
211 break;
212 }
213
214}
215
240d789c
JI
216"""
217
218def has_freeable_types(fields):
219 freeable_types = [
220 "bytearray",
221 ]
222 for field in fields:
223 if field["type"] in freeable_types:
224 return True
225 return False
226
227def is_integer_type(datatype):
228 integer_types = [
229 "uint64",
230 "uint32",
231 "uint24",
232 "uint16",
233 "uint8",
234 "int64",
235 "int32",
236 "int16",
237 "int8",
238 "dnp3time",
239 ]
240 return datatype in integer_types
241
242def to_type(datatype):
243 type_map = {
244 "uint8": "uint8_t",
245 }
246 if datatype in type_map:
247 return type_map[datatype]
248 else:
249 raise Exception("Unknown datatype: %s" % (datatype))
250
251def generate(template, filename, context):
252 print("Generating %s." % (filename))
253 try:
254 env = jinja2.Environment(trim_blocks=True)
255 output = env.from_string(template).render(context)
256 with open(filename, "w") as fileobj:
257 fileobj.write(output)
258 except Exception as err:
259 print("Failed to generate %s: %s" % (filename, err))
260 sys.exit(1)
261
262def raise_helper(msg):
263 raise Exception(msg)
264
265def gen_object_structs(context):
266 """ Generate structs for all the define DNP3 objects. """
267
268 template = """
269
270/* Code generated by:
271 * {{command_line}}
272 */
273
274{% for object in objects %}
275typedef struct DNP3ObjectG{{object.group}}V{{object.variation}}_ {
276{% for field in object.fields %}
277{% if field.type == "bstr8" %}
278{% for field in field.fields %}
279 uint8_t {{field.name}}:{{field.width}};
280{% endfor %}
281{% else %}
282{% if field.type == "int16" %}
283 int16_t {{field.name}};
284{% elif field.type == "int32" %}
285 int32_t {{field.name}};
286{% elif field.type == "uint8" %}
287 uint8_t {{field.name}};
288{% elif field.type == "uint16" %}
289 uint16_t {{field.name}};
290{% elif field.type == "uint24" %}
291 uint32_t {{field.name}};
292{% elif field.type == "uint32" %}
293 uint32_t {{field.name}};
294{% elif field.type == "uint64" %}
295 uint64_t {{field.name}};
296{% elif field.type == "flt32" %}
297 float {{field.name}};
298{% elif field.type == "flt64" %}
299 double {{field.name}};
300{% elif field.type == "dnp3time" %}
301 uint64_t {{field.name}};
302{% elif field.type == "bytearray" %}
303 uint8_t *{{field.name}};
304{% elif field.type == "vstr4" %}
305 char {{field.name}}[5];
306{% elif field.type == "chararray" %}
307 char {{field.name}}[{{field.size}}];
308{% else %}
309 {{ raise("Unknown datatype type '%s' for object %d:%d" % (
310 field.type, object.group, object.variation)) }}
311{% endif %}
312{% endif %}
313{% endfor %}
314{% if object.extra_fields %}
315{% for field in object.extra_fields %}
316{% if field.type == "uint8" %}
317 uint8_t {{field.name}};
318{% elif field.type == "uint16" %}
319 uint16_t {{field.name}};
320{% elif field.type == "uint32" %}
321 uint32_t {{field.name}};
322{% else %}
323 {{ raise("Unknown datatype: %s" % (field.type)) }}
324{% endif %}
325{% endfor %}
326{% endif %}
327} DNP3ObjectG{{object.group}}V{{object.variation}};
328
329{% endfor %}
330"""
331
332 filename = "src/app-layer-dnp3-objects.h"
333 try:
334 env = jinja2.Environment(trim_blocks=True)
335 code = env.from_string(template).render(context)
336 content = open(filename).read()
337 content = re.sub(
338 "(%s).*(%s)" % (re.escape(IN_PLACE_START), re.escape(IN_PLACE_END)),
339 r"\1%s\2" % (code), content, 1, re.M | re.DOTALL)
340 open(filename, "w").write(content)
341 print("Updated %s." % (filename))
342 except Exception as err:
343 print("Failed to update %s: %s" % (filename, err), file=sys.stderr)
344 sys.exit(1)
345
346def gen_object_decoders(context):
347 """ Generate decoders for all defined DNP3 objects. """
348
349 template = """
350
351/* Code generated by:
352 * {{command_line}}
353 */
354
355{% for object in objects %}
356{% if object.packed %}
357static int DNP3DecodeObjectG{{object.group}}V{{object.variation}}(const uint8_t **buf, uint32_t *len,
358 uint8_t prefix_code, uint32_t start, uint32_t count,
359 DNP3PointList *points)
360{
361 DNP3ObjectG{{object.group}}V{{object.variation}} *object = NULL;
362 int bytes = (count / 8) + 1;
363 uint32_t prefix = 0;
2a0bb108 364 int point_index = start;
240d789c
JI
365
366 if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
367 goto error;
368 }
369
370 for (int i = 0; i < bytes; i++) {
371
372 uint8_t octet;
373
374 if (!DNP3ReadUint8(buf, len, &octet)) {
375 goto error;
376 }
377
378 for (int j = 0; j < 8 && count; j = j + {{object.fields[0].width}}) {
379
380 object = SCCalloc(1, sizeof(*object));
381 if (unlikely(object == NULL)) {
382 goto error;
383 }
384
385{% if object.fields[0].width == 1 %}
386 object->{{object.fields[0].name}} = (octet >> j) & 0x1;
387{% elif object.fields[0].width == 2 %}
388 object->{{object.fields[0].name}} = (octet >> j) & 0x3;
389{% else %}
390#error "Unhandled field width: {{object.fields[0].width}}"
391{% endif %}
392
2a0bb108 393 if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
240d789c
JI
394 goto error;
395 }
396
397 object = NULL;
398 count--;
2a0bb108 399 point_index++;
240d789c
JI
400 }
401
402 }
403
404 return 1;
405error:
406 if (object != NULL) {
407 SCFree(object);
408 }
409 return 0;
410}
411
412{% else %}
413static int DNP3DecodeObjectG{{object.group}}V{{object.variation}}(const uint8_t **buf, uint32_t *len,
414 uint8_t prefix_code, uint32_t start, uint32_t count,
415 DNP3PointList *points)
416{
417 DNP3ObjectG{{object.group}}V{{object.variation}} *object = NULL;
418 uint32_t prefix = 0;
2a0bb108 419 uint32_t point_index = start;
240d789c
JI
420{% if object._track_offset %}
421 uint32_t offset;
422{% endif %}
423{% if object.constraints %}
424
425{% for (key, val) in object.constraints.items() %}
426{% if key == "require_size_prefix" %}
427 if (!DNP3PrefixIsSize(prefix_code)) {
428 goto error;
429 }
430{% elif key == "require_prefix_code" %}
431 if (prefix_code != {{val}}) {
432 goto error;
433 }
434{% else %}
435{{ raise("Unhandled constraint: %s" % (key)) }}
436{% endif %}
437{% endfor %}
438{% endif %}
439
440 while (count--) {
441
442 object = SCCalloc(1, sizeof(*object));
443 if (unlikely(object == NULL)) {
444 goto error;
445 }
446
447 if (!DNP3ReadPrefix(buf, len, prefix_code, &prefix)) {
448 goto error;
449 }
450{% if object._track_offset %}
451
452 offset = *len;
453{% endif %}
454
455{% for field in object.fields %}
456{% if field.type == "int16" %}
457 if (!DNP3ReadUint16(buf, len, (uint16_t *)&object->{{field.name}})) {
458 goto error;
459 }
460{% elif field.type == "int32" %}
461 if (!DNP3ReadUint32(buf, len, (uint32_t *)&object->{{field.name}})) {
462 goto error;
463 }
464{% elif field.type == "uint8" %}
465 if (!DNP3ReadUint8(buf, len, &object->{{field.name}})) {
466 goto error;
467 }
468{% elif field.type == "uint16" %}
469 if (!DNP3ReadUint16(buf, len, &object->{{field.name}})) {
470 goto error;
471 }
472{% elif field.type == "uint24" %}
473 if (!DNP3ReadUint24(buf, len, &object->{{field.name}})) {
474 goto error;
475 }
476{% elif field.type == "uint32" %}
477 if (!DNP3ReadUint32(buf, len, &object->{{field.name}})) {
478 goto error;
479 }
480{% elif field.type == "uint64" %}
481 if (!DNP3ReadUint64(buf, len, &object->{{field.name}})) {
482 goto error;
483 }
484{% elif field.type == "flt32" %}
485 if (!DNP3ReadFloat32(buf, len, &object->{{field.name}})) {
486 goto error;
487 }
488{% elif field.type == "flt64" %}
489 if (!DNP3ReadFloat64(buf, len, &object->{{field.name}})) {
490 goto error;
491 }
492{% elif field.type == "dnp3time" %}
493 if (!DNP3ReadUint48(buf, len, &object->{{field.name}})) {
494 goto error;
495 }
496{% elif field.type == "vstr4" %}
497 if (*len < 4) {
498 goto error;
499 }
500 memcpy(object->{{field.name}}, *buf, 4);
501 object->{{field.name}}[4] = '\\\\0';
502 *buf += 4;
503 *len -= 4;
504{% elif field.type == "bytearray" %}
505{% if field.len_from_prefix %}
506 object->{{field.len_field}} = prefix - (offset - *len);
507{% endif %}
508 if (object->{{field.len_field}} > 0) {
509 if (*len < object->{{field.len_field}}) {
510 /* Not enough data. */
511 goto error;
512 }
513 object->{{field.name}} = SCCalloc(1, object->{{field.len_field}});
514 if (unlikely(object->{{field.name}} == NULL)) {
515 goto error;
516 }
517 memcpy(object->{{field.name}}, *buf, object->{{field.len_field}});
518 *buf += object->{{field.len_field}};
519 *len -= object->{{field.len_field}};
520 }
521{% elif field.type == "chararray" %}
522{% if field.len_from_prefix %}
523 object->{{field.len_field}} = prefix - (offset - *len);
524{% endif %}
525 if (object->{{field.len_field}} > 0) {
6a6aa04f
PA
526 if (*len < object->{{field.len_field}}) {
527 /* Not enough data. */
528 goto error;
529 }
240d789c
JI
530 memcpy(object->{{field.name}}, *buf, object->{{field.len_field}});
531 *buf += object->{{field.len_field}};
532 *len -= object->{{field.len_field}};
533 }
534 object->{{field.name}}[object->{{field.len_field}}] = '\\\\0';
535{% elif field.type == "bstr8" %}
536 {
537 uint8_t octet;
538 if (!DNP3ReadUint8(buf, len, &octet)) {
539 goto error;
540 }
6a6aa04f 541{% set ns = namespace(shift=0) %}
240d789c
JI
542{% for field in field.fields %}
543{% if field.width == 1 %}
6a6aa04f 544 object->{{field.name}} = (octet >> {{ns.shift}}) & 0x1;
240d789c 545{% elif field.width == 2 %}
6a6aa04f 546 object->{{field.name}} = (octet >> {{ns.shift}}) & 0x3;
240d789c 547{% elif field.width == 4 %}
6a6aa04f 548 object->{{field.name}} = (octet >> {{ns.shift}}) & 0xf;
240d789c 549{% elif field.width == 7 %}
6a6aa04f 550 object->{{field.name}} = (octet >> {{ns.shift}}) & 0x7f;
240d789c
JI
551{% else %}
552{{ raise("Unhandled width of %d." % (field.width)) }}
553{% endif %}
6a6aa04f 554{% set ns.shift = ns.shift + field.width %}
240d789c
JI
555{% endfor %}
556 }
557{% else %}
558{{ raise("Unhandled datatype '%s' for object %d:%d." % (field.type,
559 object.group, object.variation)) }}
560{% endif %}
561{% endfor %}
562
2a0bb108 563 if (!DNP3AddPoint(points, object, point_index, prefix_code, prefix)) {
240d789c
JI
564 goto error;
565 }
566
567 object = NULL;
2a0bb108 568 point_index++;
240d789c
JI
569 }
570
571 return 1;
572error:
573 if (object != NULL) {
574 SCFree(object);
575 }
576
577 return 0;
578}
579
580{% endif %}
581{% endfor %}
582
583void DNP3FreeObjectPoint(int group, int variation, void *point)
584{
585 switch(DNP3_OBJECT_CODE(group, variation)) {
586{% for object in objects %}
587{% if f_has_freeable_types(object.fields) %}
588 case DNP3_OBJECT_CODE({{object.group}}, {{object.variation}}): {
589 DNP3ObjectG{{object.group}}V{{object.variation}} *object = (DNP3ObjectG{{object.group}}V{{object.variation}} *) point;
590{% for field in object.fields %}
591{% if field.type == "bytearray" %}
592 if (object->{{field.name}} != NULL) {
593 SCFree(object->{{field.name}});
594 }
595{% endif %}
596{% endfor %}
597 break;
598 }
599{% endif %}
600{% endfor %}
601 default:
602 break;
603 }
604 SCFree(point);
605}
606
607/**
608 * \\\\brief Decode a DNP3 object.
609 *
610 * \\\\retval 0 on success. On failure a positive integer corresponding
611 * to a DNP3 application layer event will be returned.
612 */
613int DNP3DecodeObject(int group, int variation, const uint8_t **buf,
614 uint32_t *len, uint8_t prefix_code, uint32_t start,
615 uint32_t count, DNP3PointList *points)
616{
617 int rc = 0;
618
619 switch (DNP3_OBJECT_CODE(group, variation)) {
620{% for object in objects %}
621 case DNP3_OBJECT_CODE({{object.group}}, {{object.variation}}):
622 rc = DNP3DecodeObjectG{{object.group}}V{{object.variation}}(buf, len, prefix_code, start, count,
623 points);
624 break;
625{% endfor %}
626 default:
627 return DNP3_DECODER_EVENT_UNKNOWN_OBJECT;
628 }
629
630 return rc ? 0 : DNP3_DECODER_EVENT_MALFORMED;
631}
632
633"""
634
635 try:
636 filename = "src/app-layer-dnp3-objects.c"
637 env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True)
638 code = env.from_string(template).render(context)
639 content = open(filename).read()
640 content = re.sub(
641 "(%s).*(%s)" % (re.escape(IN_PLACE_START), re.escape(IN_PLACE_END)),
642 r"\1%s\n\2" % (code), content, 1, re.M | re.DOTALL)
643 open(filename, "w").write(content)
644 print("Updated %s." % (filename))
645 except Exception as err:
646 print("Failed to update %s: %s" % (filename, err), file=sys.stderr)
647 sys.exit(1)
648
649def preprocess_object(obj):
650
651 valid_keys = [
652 "group",
653 "variation",
654 "constraints",
655 "extra_fields",
656 "fields",
657 "packed",
658 ]
659
660 valid_field_keys = [
661 "type",
662 "name",
663 "width",
664 "len_from_prefix",
665 "len_field",
666 "fields",
667 "size",
668 ]
669
670 if "unimplemented" in obj:
671 print("Object not implemented: %s:%s: %s" % (
672 str(obj["group"]), str(obj["variation"]), obj["unimplemented"]))
673 return None
674
675 for key, val in obj.items():
676
677 if key not in valid_keys:
678 print("Invalid key '%s' in object %d:%d" % (
679 key, obj["group"], obj["variation"]), file=sys.stderr)
680 sys.exit(1)
681
682 for field in obj["fields"]:
683
684 for key in field.keys():
685 if key not in valid_field_keys:
686 print("Invalid key '%s' in object %d:%d" % (
687 key, obj["group"], obj["variation"]), file=sys.stderr)
688 sys.exit(1)
689
690 if "len_from_prefix" in field and field["len_from_prefix"]:
691 obj["_track_offset"] = True
692 break
693
694 if field["type"] == "bstr8":
695 width = 0
696 for subfield in field["fields"]:
697 width += int(subfield["width"])
698 assert(width == 8)
699
700 return obj
701
702def main():
703
f70e8d00
JI
704 # Require Jinja2 2.10 or greater.
705 jv = jinja2.__version__.split(".")
706 if int(jv[0]) < 2 or (int(jv[0]) == 2 and int(jv[1]) < 10):
707 print("error: jinja2 v2.10 or great required")
708 return 1
709
240d789c
JI
710 definitions = yaml.load(open("scripts/dnp3-gen/dnp3-objects.yaml"))
711 print("Loaded %s objects." % (len(definitions["objects"])))
712 definitions["objects"] = map(preprocess_object, definitions["objects"])
713
714 # Filter out unimplemented objects.
715 definitions["objects"] = [
716 obj for obj in definitions["objects"] if obj != None]
717
718 context = {
719 "raise": raise_helper,
720 "objects": definitions["objects"],
721 "is_integer_type": is_integer_type,
722 "f_to_type": to_type,
723 "f_has_freeable_types": has_freeable_types,
724 "command_line": " ".join(sys.argv),
725 }
726
727 gen_object_structs(context)
728 gen_object_decoders(context)
729 generate(util_lua_dnp3_objects_c_template,
730 "src/util-lua-dnp3-objects.c",
731 context)
732 generate(output_json_dnp3_objects_template,
733 "src/output-json-dnp3-objects.c",
734 context)
735
736if __name__ == "__main__":
737 sys.exit(main())