Skip to content

Commit 9b41675

Browse files
AdamZvarasedmicha
authored andcommitted
Int_dummy: add intermediate dummy enrichment plugin
1 parent c16607d commit 9b41675

File tree

7 files changed

+988
-0
lines changed

7 files changed

+988
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# List of output plugin to build and install
22
add_subdirectory(anonymization)
3+
add_subdirectory(dummy_enricher)
34
add_subdirectory(asn)
45
add_subdirectory(geoip)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Create a linkable module
2+
add_library(dummy_enricher-intermediate MODULE
3+
dummy.c
4+
config.c
5+
config.h
6+
)
7+
8+
install(
9+
TARGETS dummy_enricher-intermediate
10+
LIBRARY DESTINATION "${INSTALL_DIR_LIB}/ipfixcol2/"
11+
)
12+
13+
if (ENABLE_DOC_MANPAGE)
14+
# Build a manual page
15+
set(SRC_FILE "${CMAKE_CURRENT_SOURCE_DIR}/doc/ipfixcol2-dummy-inter.7.rst")
16+
set(DST_FILE "${CMAKE_CURRENT_BINARY_DIR}/ipfixcol2-dummy-inter.7")
17+
18+
add_custom_command(TARGET dummy_enricher-intermediate PRE_BUILD
19+
COMMAND ${RST2MAN_EXECUTABLE} --syntax-highlight=none ${SRC_FILE} ${DST_FILE}
20+
DEPENDS ${SRC_FILE}
21+
VERBATIM
22+
)
23+
24+
install(
25+
FILES "${DST_FILE}"
26+
DESTINATION "${INSTALL_DIR_MAN}/man7"
27+
)
28+
endif()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
Dummy enrichment (intermediate plugin)
2+
===================================
3+
4+
The plugin performs enrichment of flow data with configured dummy values. It is used for testing purposes.
5+
6+
Example configuration
7+
---------------------
8+
9+
.. code-block:: xml
10+
11+
<intermediate>
12+
<name>Dummy enricher</name>
13+
<plugin>dummy_enrich</plugin>
14+
<params>
15+
<field>
16+
<pen>0</pen>
17+
<id>82</id> // Interface name
18+
<type>string</type>
19+
<str_val>enp0s3</str_val>
20+
</field>
21+
<field>
22+
<pen>0</pen>
23+
<id>86</id> // Total packets cnt
24+
<type>integer</type>
25+
<int_val>65980</int_val>
26+
<times>2</times>
27+
</field>
28+
</params>
29+
</intermediate>
30+
31+
Parameters
32+
----------
33+
34+
:``field``:
35+
Definition of added fields. Each field is defined by following parameters:
36+
37+
:``pen``:
38+
Private Enterprice number of the field.
39+
40+
:``id``:
41+
Field ID.
42+
43+
:``type``:
44+
Type of field [supported values: ``string``, ``integer``, ``double``]. Depending on type of field, one of the following value fields must be used:
45+
46+
47+
.. Notes
48+
.. -----
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
/**
2+
* \file src/plugins/intermediate/asn/asn.c
3+
* \author Adam Zvara <[email protected]>
4+
* \brief Configuration parser of ASN plugin (source file)
5+
* \date 2023
6+
*/
7+
8+
/* Copyright (C) 2018 CESNET, z.s.p.o.
9+
*
10+
* Redistribution and use in source and binary forms, with or without
11+
* modification, are permitted provided that the following conditions
12+
* are met:
13+
* 1. Redistributions of source code must retain the above copyright
14+
* notice, this list of conditions and the following disclaimer.
15+
* 2. Redistributions in binary form must reproduce the above copyright
16+
* notice, this list of conditions and the following disclaimer in
17+
* the documentation and/or other materials provided with the
18+
* distribution.
19+
* 3. Neither the name of the Company nor the names of its contributors
20+
* may be used to endorse or promote products derived from this
21+
* software without specific prior written permission.
22+
*
23+
* ALTERNATIVELY, provided that this notice is retained in full, this
24+
* product may be distributed under the terms of the GNU General Public
25+
* License (GPL) version 2 or later, in which case the provisions
26+
* of the GPL apply INSTEAD OF those given above.
27+
*
28+
* This software is provided ``as is'', and any express or implied
29+
* warranties, including, but not limited to, the implied warranties of
30+
* merchantability and fitness for a particular purpose are disclaimed.
31+
* In no event shall the company or contributors be liable for any
32+
* direct, indirect, incidental, special, exemplary, or consequential
33+
* damages (including, but not limited to, procurement of substitute
34+
* goods or services; loss of use, data, or profits; or business
35+
* interruption) however caused and on any theory of liability, whether
36+
* in contract, strict liability, or tort (including negligence or
37+
* otherwise) arising in any way out of the use of this software, even
38+
* if advised of the possibility of such damage.
39+
*
40+
*/
41+
42+
#include <stdlib.h>
43+
#include <unistd.h> // access()
44+
#include <errno.h>
45+
#include "config.h"
46+
47+
/*
48+
* <params>
49+
* <field>
50+
<pen>0</pen>
51+
<id>1234</id>
52+
<type>string</type>
53+
<value>"ABCD"</value>
54+
<times>1</times>
55+
</field>
56+
* </params>
57+
*/
58+
59+
// Strings used for parsing out type from XML file
60+
#define STRING_TYPE "string"
61+
#define INT_TYPE "integer"
62+
#define DOUBLE_TYPE "double"
63+
64+
/** XML nodes */
65+
enum params_xml_nodes {
66+
FIELD,
67+
PEN,
68+
ID,
69+
TYPE,
70+
VALUE,
71+
TIMES
72+
};
73+
74+
// New fields
75+
static const struct fds_xml_args fields_schema[] = {
76+
FDS_OPTS_ELEM(PEN, "pen", FDS_OPTS_T_UINT, 0),
77+
FDS_OPTS_ELEM(ID, "id", FDS_OPTS_T_UINT, 0),
78+
FDS_OPTS_ELEM(TYPE, "type", FDS_OPTS_T_STRING, 0),
79+
FDS_OPTS_ELEM(VALUE, "value", FDS_OPTS_T_STRING, 0),
80+
FDS_OPTS_ELEM(TIMES, "times", FDS_OPTS_T_UINT, FDS_OPTS_P_OPT),
81+
FDS_OPTS_END
82+
};
83+
84+
85+
/** Definition of the \<params\> node */
86+
static const struct fds_xml_args args_params[] = {
87+
FDS_OPTS_ROOT("params"),
88+
FDS_OPTS_NESTED(FIELD, "field", fields_schema, FDS_OPTS_P_OPT | FDS_OPTS_P_MULTI),
89+
FDS_OPTS_END
90+
};
91+
92+
static int
93+
config_parser_fields(ipx_ctx_t *ctx, fds_xml_ctx_t *fields_ctx, struct dummy_config *cfg)
94+
{
95+
const struct fds_xml_cont *fields;
96+
static size_t field_idx = 0;
97+
cfg->fields[field_idx].times = 1;
98+
99+
while (fds_xml_next(fields_ctx, &fields) != FDS_EOC) {
100+
switch (fields->id) {
101+
case PEN:
102+
cfg->fields[field_idx].pen = fields->val_uint;
103+
break;
104+
105+
case ID:
106+
cfg->fields[field_idx].id = fields->val_uint;
107+
break;
108+
109+
case TYPE:
110+
if (strcmp(fields->ptr_string, INT_TYPE) == 0) {
111+
cfg->fields[field_idx].type = DUMMY_FIELD_INT;
112+
} else if (strcmp(fields->ptr_string, STRING_TYPE) == 0) {
113+
cfg->fields[field_idx].type = DUMMY_FIELD_STRING;
114+
} else if (strcmp(fields->ptr_string, DOUBLE_TYPE) == 0) {
115+
cfg->fields[field_idx].type = DUMMY_FIELD_DOUBLE;
116+
} else {
117+
IPX_CTX_ERROR(ctx, "Unknown type of field \"type\"");
118+
return IPX_ERR_FORMAT;
119+
}
120+
break;
121+
122+
case VALUE:
123+
if (cfg->fields[field_idx].type == DUMMY_FIELD_INT) {
124+
int int_value = strtol(fields->ptr_string, NULL, 10);
125+
cfg->fields[field_idx].value.integer = int_value;
126+
} else if (cfg->fields[field_idx].type == DUMMY_FIELD_STRING) {
127+
cfg->fields[field_idx].value.string = strdup(fields->ptr_string);
128+
if (cfg->fields[field_idx].value.string == NULL) {
129+
IPX_CTX_ERROR(ctx, "Memory allocation failed (%s:%d)", __FILE__, __LINE__);
130+
return IPX_ERR_NOMEM;
131+
}
132+
} else if (cfg->fields[field_idx].type == DUMMY_FIELD_DOUBLE) {
133+
int double_value = strtod(fields->ptr_string, NULL);
134+
int64_t tmp_num = htobe64(le64toh(*(int64_t*)&double_value));
135+
double dst_num = *(double*)&tmp_num;
136+
cfg->fields[field_idx].value.decimal = dst_num;
137+
}
138+
break;
139+
140+
case TIMES:
141+
cfg->fields[field_idx].times = fields->val_uint;
142+
break;
143+
144+
default:
145+
IPX_CTX_ERROR(ctx, "Unknown field in configuration (ID %d)", fields->id);
146+
return IPX_ERR_FORMAT;
147+
}
148+
149+
}
150+
151+
field_idx++;
152+
return IPX_OK;
153+
}
154+
155+
/**
156+
* \brief Process \<params\> node
157+
* \param[in] ctx Plugin context
158+
* \param[in] root XML context to process
159+
* \param[in] cfg Parsed configuration
160+
* \return #IPX_OK on success
161+
* \return #IPX_ERR_FORMAT in case of failure
162+
*/
163+
static int
164+
config_parser_root(ipx_ctx_t *ctx, fds_xml_ctx_t *root, struct dummy_config *cfg)
165+
{
166+
(void) ctx;
167+
const struct fds_xml_cont *content;
168+
169+
// First, get number of new fields and allocate memory in config structure
170+
while (fds_xml_next(root, &content) != FDS_EOC) {
171+
if (content->id != FIELD) {
172+
// Non-field definition
173+
assert(false);
174+
continue;
175+
}
176+
cfg->fields_count++;
177+
}
178+
179+
cfg->fields = calloc(cfg->fields_count, sizeof(*cfg->fields));
180+
if (!cfg->fields) {
181+
IPX_CTX_ERROR(ctx, "Memory allocation error (%s:%d)", __FILE__, __LINE__);
182+
return IPX_ERR_FORMAT;
183+
}
184+
185+
// Rewind pointer and start parsing
186+
fds_xml_rewind(root);
187+
while (fds_xml_next(root, &content) != FDS_EOC) {
188+
if (content->id != FIELD) {
189+
return IPX_ERR_FORMAT;
190+
}
191+
192+
assert(content->type == FDS_OPTS_T_CONTEXT);
193+
if (config_parser_fields(ctx, content->ptr_ctx, cfg) != IPX_OK) {
194+
return IPX_ERR_FORMAT;
195+
}
196+
}
197+
198+
return IPX_OK;
199+
}
200+
201+
struct dummy_config *
202+
config_parse(ipx_ctx_t *ctx, const char *params)
203+
{
204+
struct dummy_config *cfg = calloc(1, sizeof(*cfg));
205+
if (!cfg) {
206+
IPX_CTX_ERROR(ctx, "Memory allocation error (%s:%d)", __FILE__, __LINE__);
207+
return NULL;
208+
}
209+
210+
// Create an XML parser
211+
fds_xml_t *parser = fds_xml_create();
212+
if (!parser) {
213+
IPX_CTX_ERROR(ctx, "Memory allocation error (%s:%d)", __FILE__, __LINE__);
214+
free(cfg);
215+
return NULL;
216+
}
217+
if (fds_xml_set_args(parser, args_params) != IPX_OK) {
218+
IPX_CTX_ERROR(ctx, "Failed to parse the description of an XML document!", '\0');
219+
fds_xml_destroy(parser);
220+
free(cfg);
221+
return NULL;
222+
}
223+
224+
fds_xml_ctx_t *params_ctx = fds_xml_parse_mem(parser, params, true);
225+
if (params_ctx == NULL) {
226+
IPX_CTX_ERROR(ctx, "Failed to parse the configuration: %s", fds_xml_last_err(parser));
227+
fds_xml_destroy(parser);
228+
free(cfg);
229+
return NULL;
230+
}
231+
232+
// Parse parameters
233+
int rc = config_parser_root(ctx, params_ctx, cfg);
234+
fds_xml_destroy(parser);
235+
if (rc != IPX_OK) {
236+
free(cfg);
237+
return NULL;
238+
}
239+
240+
return cfg;
241+
}
242+
243+
void
244+
config_destroy(struct dummy_config *cfg)
245+
{
246+
for (uint32_t i = 0; i < cfg->fields_count; ++i) {
247+
if (cfg->fields[i].type == DUMMY_FIELD_STRING) {
248+
free(cfg->fields[i].value.string);
249+
}
250+
}
251+
free(cfg->fields);
252+
free(cfg);
253+
}

0 commit comments

Comments
 (0)