Skip to content

Commit 4fe08e0

Browse files
committed
Unirec output plugin: added new extracted feature in the mapping parser
1 parent 9341cd5 commit 4fe08e0

File tree

2 files changed

+80
-19
lines changed

2 files changed

+80
-19
lines changed

extra_plugins/output/unirec/map.c

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454

5555
/** Internal structure of the mapping database */
5656
struct map_s {
57+
/** Manager of IPFIX Information Elements */
58+
const fds_iemgr_t *iemgr;
59+
5760
/** Size of valid records */
5861
size_t rec_size;
5962
/** Size of pre-allocated array */
@@ -66,8 +69,12 @@ struct map_s {
6669
};
6770

6871
map_t *
69-
map_init()
72+
map_init(const fds_iemgr_t *ie_mgr)
7073
{
74+
if (!ie_mgr) {
75+
return NULL;
76+
}
77+
7178
struct map_s *res = calloc(1, sizeof(*res));
7279
if (!res) {
7380
return NULL;
@@ -82,6 +89,7 @@ map_init()
8289
}
8390

8491
snprintf(res->err_buffer, ERR_SIZE, "No error");
92+
res->iemgr = ie_mgr;
8593
return res;
8694
}
8795

@@ -91,6 +99,7 @@ map_clear(map_t *map)
9199
for (size_t i = 0; i < map->rec_size; ++i) {
92100
struct map_rec *rec = map->rec_array[i];
93101
free(rec->unirec.name);
102+
free(rec->unirec.type_str);
94103
free(rec);
95104
}
96105

@@ -159,8 +168,11 @@ map_rec_add(map_t *map, const struct map_rec *rec)
159168

160169
*new_rec = *rec;
161170
new_rec->unirec.name = strdup(rec->unirec.name);
162-
if (!new_rec->unirec.name) {
171+
new_rec->unirec.type_str = strdup(rec->unirec.type_str);
172+
if (!new_rec->unirec.name || !new_rec->unirec.type_str) {
163173
snprintf(map->err_buffer, ERR_SIZE, "Memory allocation error");
174+
free(new_rec->unirec.name);
175+
free(new_rec->unirec.type_str);
164176
free(new_rec);
165177
return IPX_ERR_NOMEM;
166178
}
@@ -169,11 +181,40 @@ map_rec_add(map_t *map, const struct map_rec *rec)
169181
return IPX_OK;
170182
}
171183

184+
/**
185+
* \brief Get the definition of an IPFIX Information Element
186+
* \param[in] mgr Manager of IPFIX Information Elements (IE)
187+
* \param[in] elem Information Element to find
188+
* \return Pointer to the definition or NULL (unknown or invalid IE specifier)
189+
*/
190+
static const struct fds_iemgr_elem *
191+
map_elem_get(fds_iemgr_t *mgr, const char *elem)
192+
{
193+
const struct fds_iemgr_elem *res;
194+
195+
// Try to find the identifier
196+
res = fds_iemgr_elem_find_name(mgr, elem);
197+
if (res != NULL) {
198+
return res;
199+
}
200+
201+
// Try to parse "old style" specifier
202+
uint32_t ipfix_en;
203+
uint16_t ipfix_id;
204+
205+
char aux;
206+
if (sscanf(elem, "e%"SCNu32"id%"SCNu16"%c", &ipfix_en, &ipfix_id, &aux) != 2) {
207+
return NULL;
208+
}
209+
210+
return fds_iemgr_elem_find_id(map->iemgr, ipfix_en, ipfix_id);
211+
}
212+
172213
/**
173214
* \brief Parse a line of a configuration file and add records to the database
174-
* \param[in] map Mapping database
175-
* \param[in] line Line to parse
176-
* \param[in] line_id Line ID (just for error messages)
215+
* \param[in] map Mapping database
216+
* \param[in,out] line Line to parse (could be modified!)
217+
* \param[in] line_id Line ID (just for error messages)
177218
* \return #IPX_OK on success
178219
* \return #IPX_ERR_FORMAT or #IPX_ERR_NOMEM on failure (an error message is set)
179220
*/
@@ -216,14 +257,23 @@ map_load_line(map_t *map, char *line, size_t line_id)
216257
}
217258
ur_type = type;
218259

260+
char *ur_type_str = strdup(token);
261+
if (!ur_type_str) {
262+
snprintf(map->err_buffer, ERR_SIZE, "Memory allocation error");
263+
free(ur_name);
264+
return IPX_ERR_NOMEM;
265+
}
266+
219267
struct map_rec rec;
220268
rec.unirec.name = ur_name;
221269
rec.unirec.type = ur_type;
270+
rec.unirec.type_str = ur_type_str;
222271

223272
// Get list of IPFIX fields
224273
token = strtok_r(NULL, delim, &save_ptr);
225274
if (!token) {
226275
snprintf(map->err_buffer, ERR_SIZE, "Line %zu: Unexpected end of line!", line_id);
276+
free(ur_type_str);
227277
free(ur_name);
228278
return IPX_ERR_FORMAT;
229279
}
@@ -239,18 +289,23 @@ map_load_line(map_t *map, char *line, size_t line_id)
239289
}
240290

241291
// Parse IPFIX specifier
242-
char aux;
243-
if (sscanf(subtoken, "e%"SCNu32"id%"SCNu16"%c", &rec.ipfix.en, &rec.ipfix.id, &aux) != 2) {
244-
snprintf(map->err_buffer, ERR_SIZE, "Line %zu: Invalid IPFIX specifier '%s'",
245-
line_id, subtoken);
292+
const struct fds_iemgr_elem *elem_def = map_elem_get(map, subtoken);
293+
if (!elem_def) {
294+
snprintf(map->err_buffer, ERR_SIZE, "Line %zu: IPFIX specifier '%s' is invalid or "
295+
"a definition of the Information Element is missing! For more information, see "
296+
"the plugin documentation.", line_id, subtoken);
246297
rc = IPX_ERR_FORMAT;
247298
break;
248299
}
249300

250301
// Store the record
302+
rec.ipfix.def = elem_def;
303+
rec.ipfix.id = elem_def->id;
304+
rec.ipfix.en = elem_def->scope->pen;
251305
rc = map_rec_add(map, &rec);
252306
}
253307

308+
free(ur_type_str);
254309
free(ur_name);
255310
return rc;
256311
}
@@ -349,9 +404,10 @@ map_load(map_t *map, const char *file)
349404
}
350405

351406
// Collision detected!
352-
snprintf(map->err_buffer, ERR_SIZE, "The same IPFIX IE (PEN %" PRIu32 ", ID %" PRIu16 ") "
353-
"is mapped to different UniRec fields ('%s' and '%s')",
354-
rec_now->ipfix.en, rec_now->ipfix.id, rec_now->unirec.name, rec_prev->unirec.name);
407+
snprintf(map->err_buffer, ERR_SIZE, "The IPFIX IE '%s' (PEN %" PRIu32 ", ID %" PRIu16 ") "
408+
"is mapped to multiple different UniRec fields ('%s' and '%s')",
409+
rec_now->ipfix.def->name, rec_now->ipfix.en, rec_now->ipfix.id,
410+
rec_now->unirec.name, rec_prev->unirec.name);
355411
map_clear(map);
356412
return IPX_ERR_FORMAT;
357413
}

extra_plugins/output/unirec/map.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,29 +49,34 @@
4949
/** Internal map type */
5050
typedef struct map_s map_t;
5151

52-
/** IPFIX-to-UniRec mapping record */
52+
/** IPFIX-to-UniRec mapping record */
5353
struct map_rec {
5454
struct {
55-
/** Private Enterprise Number */
55+
/** Private Enterprise Number */
5656
uint32_t en;
57-
/** Information Element ID */
57+
/** Information Element ID */
5858
uint16_t id;
59-
} ipfix; /**< IPFIX specific parameters */
59+
/** Definition of the IE (MUST not be NULL) */
60+
const struct fds_iemgr_elem *def;
61+
} ipfix; /**< IPFIX specific parameters */
6062

6163
struct {
62-
/** Field name */
64+
/** Field name */
6365
char *name;
64-
/** Data type */
66+
/** Data type */
6567
ur_field_type_t type;
68+
/** Data type (string, for log!) */
69+
char *type_str;
6670
} unirec;
6771
};
6872

6973
/**
7074
* \brief Initialize a mapping database
75+
* \param[in] ie_mgr Reference to a manager of Information Elements
7176
* \return Pointer to the new DB
7277
*/
7378
map_t *
74-
map_init();
79+
map_init(const fds_iemgr_t *ie_mgr);
7580

7681
/**
7782
* \brief Destroy a mapping database

0 commit comments

Comments
 (0)