From 0ec65cf851184bf6d9b6dfa95e344613f78c9588 Mon Sep 17 00:00:00 2001 From: Lukas Hutak Date: Thu, 14 Mar 2019 15:13:40 +0100 Subject: [PATCH] UniRec output: added "string_trimmed" type for string trimming during conversion --- extra_plugins/output/unirec/src/map.c | 19 ++++++++++++++--- extra_plugins/output/unirec/src/map.h | 10 +++++++++ extra_plugins/output/unirec/src/translator.c | 21 +++++++++++++++++++ .../output/unirec/src/unirecplugin.c | 2 +- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/extra_plugins/output/unirec/src/map.c b/extra_plugins/output/unirec/src/map.c index 130ac8b9..d5b96768 100644 --- a/extra_plugins/output/unirec/src/map.c +++ b/extra_plugins/output/unirec/src/map.c @@ -52,6 +52,8 @@ #define DEF_SIZE 32 /** Size of error buffer */ #define ERR_SIZE 256 +/** Special type of UniRec string field that is trimmed before conversion from IPFIX */ +#define TYPE_STRING_TRIM "string_trimmed" /** Internal structure of the mapping database */ struct map_s { @@ -234,13 +236,14 @@ map_elem_get_internal(const char *elem) * \param[in] ur_name UniRec name * \param[in] ur_type UniRec type * \param[in] ur_type_str UniRec type string + * \param[in] cflags Additional conversion flags * \param[in] ie_defs Definition of IPFIX IEs (comma separated list of definitions) * \param[in] line_id Line ID (just for error messages) * \return #IPX_OK on success * \return #IPX_ERR_NOMEM or #IPX_ERR_FORMAT on failure */ static int -map_load_line_ie_defs(map_t *map, char *ur_name, int ur_type, char *ur_type_str, +map_load_line_ie_defs(map_t *map, char *ur_name, int ur_type, char *ur_type_str, uint32_t cflags, const char *ie_defs, size_t line_id) { char *defs_cpy = strdup(ie_defs); @@ -264,6 +267,7 @@ map_load_line_ie_defs(map_t *map, char *ur_name, int ur_type, char *ur_type_str, rec.unirec.name = ur_name; rec.unirec.type = ur_type; rec.unirec.type_str = ur_type_str; + rec.unirec.flags = cflags; // Process IPFIX fields char *subsave_ptr = NULL; @@ -323,6 +327,7 @@ map_load_line(map_t *map, const char *line, size_t line_id) int rc = IPX_OK; char *ur_name = NULL; char *ur_type_str = NULL; + uint32_t conv_flags = 0; ur_field_type_t ur_type; char *line_cpy = strdup(line); @@ -356,7 +361,15 @@ map_load_line(map_t *map, const char *line, size_t line_id) goto end; } - int type = ur_get_field_type_from_str(token); + int type; + if (strcmp(token, TYPE_STRING_TRIM) == 0) { + // Special version of string + type = UR_TYPE_STRING; + conv_flags |= MAP_FLAGS_STR_TRIM; + } else { + type = ur_get_field_type_from_str(token); + } + if (type == UR_E_INVALID_TYPE) { snprintf(map->err_buffer, ERR_SIZE, "Line %zu: Invalid type '%s' of UniRec field '%s'", line_id, token, ur_name); @@ -382,7 +395,7 @@ map_load_line(map_t *map, const char *line, size_t line_id) ptrdiff_t offset = token - line_cpy; const char *ie_defs = line + offset; - rc = map_load_line_ie_defs(map, ur_name, ur_type, ur_type_str, ie_defs, line_id); + rc = map_load_line_ie_defs(map, ur_name, ur_type, ur_type_str, conv_flags, ie_defs, line_id); end: free(ur_type_str); diff --git a/extra_plugins/output/unirec/src/map.h b/extra_plugins/output/unirec/src/map.h index 420570e6..35c4cad1 100644 --- a/extra_plugins/output/unirec/src/map.h +++ b/extra_plugins/output/unirec/src/map.h @@ -61,6 +61,11 @@ enum MAP_SRC { MAP_SRC_INTERNAL_DBF }; +enum MAP_FLAGS { + /** Perform trim of an IPFIX string (convert only characters before the first '\0') */ + MAP_FLAGS_STR_TRIM = (1 << 0) +}; + /** IPFIX-to-UniRec mapping record */ struct map_rec { struct { @@ -85,6 +90,11 @@ struct map_rec { ur_field_type_t type; /** Data type (string, for log!) */ char *type_str; + /** + * \brief Additional conversion flags + * \note See ::MAP_FLAGS + */ + uint32_t flags; } unirec; }; diff --git a/extra_plugins/output/unirec/src/translator.c b/extra_plugins/output/unirec/src/translator.c index db3730ee..899bf9f6 100644 --- a/extra_plugins/output/unirec/src/translator.c +++ b/extra_plugins/output/unirec/src/translator.c @@ -316,6 +316,22 @@ translate_bytes(translator_t *trans, const struct translator_rec *rec, return 0; } +/** + * \brief Convert IPFIX string to trimmed UniRec string + * + * The function will copy only characters up to the first occurrence of '\0' (excluding). + * \copydetails translate_uint() + */ +static int +translator_string_trim(translator_t *trans, const struct translator_rec *rec, + const struct fds_drec_field *field) +{ + ur_field_id_t ur_id = rec->unirec.id; + size_t copy_len = strnlen((const char *) field->data, field->size); + ur_set_var(trans->record.ur_tmplt, trans->record.data, ur_id, field->data, copy_len); + return 0; +} + /** * \brief Convert IPFIX boolean to UniRec char/(un)signed integer * \copydetails translate_uint() @@ -699,6 +715,11 @@ translator_get_func(ipx_ctx_t *ctx, const struct map_rec *rec) switch (type_ur) { case UR_TYPE_STRING: + // String array + if (type_ipx == FDS_ET_STRING && (rec->unirec.flags & MAP_FLAGS_STR_TRIM) != 0) { + return translator_string_trim; + } + // Fall through case UR_TYPE_BYTES: // String/byte array if (type_ipx == FDS_ET_STRING || type_ipx == FDS_ET_OCTET_ARRAY) { diff --git a/extra_plugins/output/unirec/src/unirecplugin.c b/extra_plugins/output/unirec/src/unirecplugin.c index 48cdfa3d..e7279451 100644 --- a/extra_plugins/output/unirec/src/unirecplugin.c +++ b/extra_plugins/output/unirec/src/unirecplugin.c @@ -78,7 +78,7 @@ IPX_API struct ipx_plugin_info ipx_plugin_info = { // Configuration flags (reserved for future use) .flags = 0, // Plugin version string (like "1.2.3") - .version = "2.0.0", + .version = "2.1.0", // Minimal IPFIXcol version string (like "1.2.3") .ipx_min = "2.0.0" };