5454
5555/** Internal structure of the mapping database */
5656struct 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
6871map_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 }
0 commit comments