@@ -99,7 +99,8 @@ mmdb_lookup(MMDB_s *db, struct sockaddr *address, int *err)
9999{
100100 assert (db != NULL && address != NULL && err != NULL );
101101
102- int rc = MMDB_SUCCESS ;
102+ int rc ;
103+ * err = MMDB_SUCCESS ;
103104 MMDB_lookup_result_s result ;
104105
105106 // Search for address
@@ -166,15 +167,21 @@ get_asn(MMDB_s *db, struct ipx_modifier_output *out, uint8_t *address, size_t le
166167 return IPX_ERR_ARG ;
167168 }
168169
169- asn = mmdb_lookup (db , addr , & rc );
170+ asn = htonl ( mmdb_lookup (db , addr , & rc ) );
170171 if (rc ) {
171172 // MMDB error
172173 return IPX_ERR_DENIED ;
173174 }
174175
176+ if (asn == 0 ) {
177+ // Not found
178+ return IPX_OK ;
179+ }
180+
175181 int len = 4 ;
176182 memcpy (out -> raw , & asn , len );
177183 out -> length = len ;
184+ return IPX_OK ;
178185}
179186
180187
@@ -224,6 +231,8 @@ modifier_asn_callback(const struct fds_drec *rec, struct ipx_modifier_output out
224231 if (rc ) {
225232 return rc ;
226233 }
234+
235+ return IPX_OK ;
227236}
228237
229238/**
@@ -279,6 +288,120 @@ process_session(ipx_ctx_t *ctx, ipx_modifier_t *modifier, ipx_msg_session_t *msg
279288 return IPX_OK ;
280289}
281290
291+ /**
292+ * \brief Free modified record
293+ *
294+ * \param[in] rec Data record
295+ */
296+ void
297+ free_modified_record (struct fds_drec * rec )
298+ {
299+ free (rec -> data );
300+ free (rec );
301+ }
302+
303+ /**
304+ * \brief Estimate size of new message based on old message
305+ *
306+ * Estimation counts with worst case scenario, which is that in new message,
307+ * for each data record new set is created and both AS numbers are added
308+ * \param[in] msg IPFIX message
309+ * \return Estimated size
310+ */
311+ int
312+ estimate_new_length (ipx_msg_ipfix_t * msg )
313+ {
314+ const struct fds_ipfix_msg_hdr * hdr = (struct fds_ipfix_msg_hdr * ) ipx_msg_ipfix_get_packet (msg );
315+ uint32_t rec_cnt = ipx_msg_ipfix_get_drec_cnt (msg );
316+ uint32_t msg_size = ntohs (hdr -> length );
317+
318+ if (rec_cnt == 0 ) {
319+ return msg_size ;
320+ }
321+
322+ //for each record * (size of new header + 2x ASN + size of single record)
323+ return rec_cnt * (FDS_IPFIX_SET_HDR_LEN + 8 + msg_size / rec_cnt );
324+ }
325+
326+ /**
327+ * \brief Add new session context from current message to modifier
328+ *
329+ * \param[in] ctx Plugin context
330+ * \param[in] modifier Modifier
331+ * \param[in] msg IPFIX message
332+ * \return #IPX_OK on success
333+ * \return #IPX_ERR_ARG on invalid arguments
334+ * \return #IPX_ERR_NOMEM on memory allocation error
335+ */
336+ int
337+ ipfix_add_session (ipx_ctx_t * ctx , ipx_modifier_t * modifier , ipx_msg_ipfix_t * msg )
338+ {
339+ int rc ;
340+
341+ // Update modifier session context
342+ ipx_msg_garbage_t * session_garbage ;
343+ rc = ipx_modifier_add_session (modifier , msg , & session_garbage );
344+ if (session_garbage ) {
345+ ipx_ctx_msg_pass (ctx , ipx_msg_garbage2base (session_garbage ));
346+ }
347+
348+ if (rc ) {
349+ switch (rc ) {
350+ case IPX_ERR_ARG :
351+ IPX_CTX_ERROR (ctx , "Invalid arguments passed to ipx_modifier_add_session (%s:%d)" ,
352+ __FILE__ , __LINE__ );
353+ return rc ;
354+ case IPX_ERR_FORMAT :
355+ // Setting time in history for TCP should be blocked by parser
356+ assert (false);
357+ case IPX_ERR_NOMEM :
358+ IPX_CTX_ERROR (ctx , "Memory allocation error (%s:%d)" , __FILE__ , __LINE__ );
359+ return rc ;
360+ default :
361+ IPX_CTX_ERROR (ctx , "Unexpected error from ipx_modifier_add_session (%s:%d)" ,
362+ __FILE__ , __LINE__ );
363+ return rc ;
364+ }
365+ }
366+
367+ return IPX_OK ;
368+ }
369+
370+ /**
371+ * \brief Start building new message
372+ *
373+ * \param[in] ctx Plugin context
374+ * \param[in] modifier Modifier
375+ * \param[in] msg IPFIX message
376+ * \return #IPX_OK on success
377+ * \return #IPX_ERR_ARG on invalid arguments
378+ * \return #IPX_ERR_NOMEM on memory allocation error
379+ */
380+ int
381+ ipfix_start_builder (ipx_ctx_t * ctx , ipx_msg_builder_t * builder ,
382+ const struct fds_ipfix_msg_hdr * hdr , const size_t maxsize )
383+ {
384+ int rc = ipx_msg_builder_start (builder , hdr , maxsize , 0 );
385+
386+ if (rc ) {
387+ switch (rc ) {
388+ case IPX_ERR_ARG :
389+ IPX_CTX_ERROR (ctx , "Invalid arguments passed to ipx_modifier_add_session (%s:%d)" ,
390+ __FILE__ , __LINE__ );
391+ return rc ;
392+ case IPX_ERR_NOMEM :
393+ IPX_CTX_ERROR (ctx , "Memory allocation error (%s:%d)" , __FILE__ , __LINE__ );
394+ return rc ;
395+ default :
396+ IPX_CTX_ERROR (ctx , "Unexpected error from ipx_modifier_add_session (%s:%d)" ,
397+ __FILE__ , __LINE__ );
398+ return rc ;
399+ }
400+ }
401+
402+ return IPX_OK ;
403+ }
404+
282405/**
283406 * \brief Process IPFIX message
284407 *
@@ -288,26 +411,81 @@ process_session(ipx_ctx_t *ctx, ipx_modifier_t *modifier, ipx_msg_session_t *msg
288411 * \param[in] modifier Modifier component
289412 * \param[in] builder Message builder
290413 * \param[in] msg IPFIX message
291- * \return
414+ * \return #IPX_OK on success
415+ * \return #IPX_ERR_DENIED on any error
292416 */
293417static int
294418process_ipfix (ipx_ctx_t * ctx , ipx_modifier_t * modifier , ipx_msg_builder_t * builder ,
295419 ipx_msg_ipfix_t * msg )
296420{
421+ int rc ;
297422
298- ipx_msg_garbage_t * session_garbage ;
299- ipx_modifier_add_session (modifier , msg , & session_garbage );
423+ // Add session
424+ rc = ipfix_add_session (ctx , modifier , msg );
425+ if (rc ) {
426+ return rc ;
427+ }
300428
301- uint32_t rec_cnt = ipx_msg_ipfix_get_drec_cnt (msg );
429+ // Estimate size of new message
430+ size_t new_msg_size = estimate_new_length (msg );
302431
432+ // Start builder
433+ const struct fds_ipfix_msg_hdr * hdr = (struct fds_ipfix_msg_hdr * ) ipx_msg_ipfix_get_packet (msg );
434+ rc = ipfix_start_builder (ctx , builder , hdr , new_msg_size );
435+ if (rc ) {
436+ return rc ;
437+ }
438+
439+ // Modify each record in IPFIX message and store modified record in builder
440+ uint32_t rec_cnt = ipx_msg_ipfix_get_drec_cnt (msg );
303441 struct ipx_ipfix_record * rec ;
442+ struct fds_drec * modified_rec ;
304443 ipx_msg_garbage_t * ipfix_garbage ;
305444 for (uint32_t i = 0 ; i < rec_cnt ; i ++ ) {
306445 rec = ipx_msg_ipfix_get_drec (msg , i );
307446
308- ipx_modifier_modify (modifier , & (rec -> rec ), & ipfix_garbage );
447+ // Modify record
448+ modified_rec = ipx_modifier_modify (modifier , & (rec -> rec ), & ipfix_garbage );
449+ if (ipfix_garbage ) {
450+ ipx_ctx_msg_pass (ctx , ipx_msg_garbage2base (ipfix_garbage ));
451+ }
452+ if (!modified_rec ) {
453+ // Proper message has been already printed
454+ return rc ;
455+ }
456+
457+ // Store modified record in builder
458+ rc = ipx_msg_builder_add_drec (builder , modified_rec );
459+
460+ if (rc ) {
461+ free_modified_record (modified_rec );
462+ switch (rc ) {
463+ case IPX_ERR_DENIED :
464+ // Exceeded builder limit
465+ IPX_CTX_ERROR (ctx , "Exceeded message builder limit" , __FILE__ , __LINE__ );
466+ return rc ;
467+ case IPX_ERR_NOMEM :
468+ IPX_CTX_ERROR (ctx , "Memory allocation error (%s:%d)" , __FILE__ , __LINE__ );
469+ return rc ;
470+ default :
471+ IPX_CTX_ERROR (ctx , "Unexpected error from ipx_modifier_add_session (%s:%d)" ,
472+ __FILE__ , __LINE__ );
473+ return rc ;
474+ }
475+ }
476+
477+ free_modified_record (modified_rec );
309478 }
310479
480+ // Create new message with modified records
481+ const struct ipx_msg_ctx * msg_ctx = ipx_msg_ipfix_get_ctx (msg );
482+ ipx_msg_ipfix_t * new_msg = ipx_msg_builder_end (builder , ctx , msg_ctx );
483+ if (!new_msg ) {
484+ return IPX_ERR_DENIED ;
485+ }
486+
487+ ipx_msg_ipfix_destroy (msg );
488+ ipx_ctx_msg_pass (ctx , ipx_msg_ipfix2base (new_msg ));
311489 return IPX_OK ;
312490}
313491
@@ -419,8 +597,10 @@ ipx_plugin_process(ipx_ctx_t *ctx, void *cfg, ipx_msg_t *msg)
419597 }
420598
421599 if (rc ) {
422- // Any problem occured in processing message
423- return IPX_ERR_DENIED ;
600+ // Any problem occured when modifying message
601+ // pass original message
602+ ipx_ctx_msg_pass (ctx , msg );
603+ return IPX_OK ;
424604 }
425605
426606 return IPX_OK ;
0 commit comments