@@ -137,8 +137,8 @@ struct translator_s {
137137 } progress ; /**< Auxiliary conversion variables */
138138
139139 struct {
140- /** IPFIX Message header */
141- const struct fds_ipfix_msg_hdr * hdr ;
140+ /** IPFIX Message context */
141+ const struct ipx_msg_ctx * ctx ;
142142 } msg_context ; /**< IPFIX context of the record to translate */
143143
144144 struct {
@@ -151,6 +151,18 @@ struct translator_s {
151151 int field_size ; /**< UniRec field size */
152152 ur_field_id_t field_id ; /**< UniRec field ID */
153153 } lbf ; /**< ODID to 'link bit field' converter */
154+ struct
155+ {
156+ bool en ; /**< Enabled/disabled */
157+ int req_idx ; /**< Index in the template */
158+ ur_field_id_t field_id ; /**< UniRec field ID */
159+ } odid ; /**< ODID from IPFIX Message header */
160+ struct
161+ {
162+ bool en ; /**< Enabled/disabled */
163+ int req_idx ; /**< Index in the template */
164+ ur_field_id_t field_id ; /**< UniRec field ID */
165+ } exporter_ip ; /**< Exporter IP address from message session */
154166 } extra_conv ; /**< Special internal conversion functions */
155167};
156168
@@ -802,12 +814,12 @@ translate_internal_dbf(translator_t *trans, const struct translator_rec *rec,
802814static int
803815translate_internal_lbf (translator_t * trans )
804816{
805- if (!trans -> msg_context .hdr ) {
806- return 1 ; // Message header is not available!
817+ if (!trans -> msg_context .ctx ) {
818+ return 1 ; // Message context is not available!
807819 }
808820
809821 // Get the ODID value
810- uint32_t odid = ntohl ( trans -> msg_context .hdr -> odid ) ;
822+ uint32_t odid = trans -> msg_context .ctx -> odid ;
811823
812824 // Store the value is 'link bit field'
813825 ur_field_type_t ur_id = trans -> extra_conv .lbf .field_id ;
@@ -833,6 +845,83 @@ translate_internal_lbf(translator_t *trans)
833845 return 0 ;
834846}
835847
848+ /**
849+ * \brief Convert (fill) ODID field
850+ *
851+ * \note This function uses a message context configured by the user. It's independent on the
852+ * content of an IPFIX record.
853+ * \param[in] trans Internal translator structure
854+ * \return On success returns 0. Otherwise returns non-zero value!
855+ */
856+ static int
857+ translate_internal_odid (translator_t * trans )
858+ {
859+ if (!trans -> msg_context .ctx ) {
860+ return 1 ; // Message context is not available!
861+ }
862+
863+ // Get the ODID value
864+ uint32_t odid = trans -> msg_context .ctx -> odid ;
865+
866+ ur_field_type_t ur_id = trans -> extra_conv .odid .field_id ;
867+ void * field_ptr = ur_get_ptr_by_id (trans -> record .ur_tmplt , trans -> record .data , ur_id );
868+
869+ * ((uint32_t * ) field_ptr ) = odid ;
870+
871+ return 0 ;
872+ }
873+
874+ /**
875+ * \brief Convert (fill) EXPORTER_IP field with IPv4 or IPv6 address from IPFIX
876+ * message session.
877+ *
878+ * \note This function uses a message context configured by the user. It's independent on the
879+ * content of an IPFIX record.
880+ * \param[in] trans Internal translator structure
881+ * \return On success returns 0. Otherwise returns non-zero value!
882+ */
883+ static int
884+ translate_internal_exporter_ip (translator_t * trans )
885+ {
886+ if (!trans -> msg_context .ctx ) {
887+ return 1 ; // Message context is not available!
888+ }
889+
890+ const struct ipx_session * session = trans -> msg_context .ctx -> session ;
891+
892+ const struct ipx_session_net * session_net ;
893+ switch (session -> type )
894+ {
895+ case FDS_SESSION_UDP :
896+ session_net = & session -> udp .net ;
897+ break ;
898+ case FDS_SESSION_TCP :
899+ session_net = & session -> tcp .net ;
900+ break ;
901+ case FDS_SESSION_SCTP :
902+ session_net = & session -> sctp .net ;
903+ break ;
904+ default :
905+ // Uncompatible type of message session. E.g. messages from file.
906+ return 1 ;
907+ }
908+
909+ // Get pointer to save result IP
910+ ur_field_type_t ur_id = trans -> extra_conv .exporter_ip .field_id ;
911+ void * field_ptr = ur_get_ptr_by_id (trans -> record .ur_tmplt , trans -> record .data , ur_id );
912+
913+ if (session -> udp .net .l3_proto == AF_INET ) {
914+ * ((ip_addr_t * ) field_ptr ) = ip_from_4_bytes_be ((char * ) & session_net -> addr_src .ipv4 .s_addr );
915+ } else if (session -> udp .net .l3_proto == AF_INET6 ) {
916+ * ((ip_addr_t * ) field_ptr ) = ip_from_16_bytes_be ((char * ) session_net -> addr_src .ipv6 .s6_addr );
917+ } else {
918+ // Unknown IP protocol
919+ return 1 ;
920+ }
921+
922+ return 0 ;
923+ }
924+
836925/**
837926 * \brief Get size of UniRec numeric data types
838927 * \param type UniRec data types
@@ -1451,6 +1540,62 @@ translator_table_fill_internal(translator_t *trans, const struct map_rec *map_re
14511540 return IPX_OK ;
14521541 }
14531542
1543+ /* Internal "ODID field" function
1544+ * Implemented as a special converter that must be enabled in the translator because
1545+ * ODID is not defined in the IPFIX record but in the IPFIX Message header
1546+ */
1547+ if (src == MAP_SRC_INTERNAL_ODID ) {
1548+ if (trans -> extra_conv .odid .en ) {
1549+ // The function is already enabled!
1550+ IPX_CTX_ERROR (trans -> ctx , "Internal 'odid field' function can be mapped only "
1551+ "to one UniRec field!" , '\0' );
1552+ return IPX_ERR_DENIED ;
1553+ }
1554+
1555+ if (ur_type != UR_TYPE_UINT32 ) {
1556+ IPX_CTX_ERROR (trans -> ctx , "Internal 'odid field' function supports only UniRec "
1557+ "uint32 type but UniRec field '%s' is '%s'!" , map_rec -> unirec .name ,
1558+ map_rec -> unirec .type_str );
1559+ return IPX_ERR_DENIED ;
1560+ }
1561+
1562+ // Enable the internal converter
1563+ trans -> extra_conv .odid .en = true;
1564+ trans -> extra_conv .odid .req_idx = field_idx ;
1565+ trans -> extra_conv .odid .field_id = ur_id ;
1566+ IPX_CTX_DEBUG (trans -> ctx , "Added conversion from internal 'odid field' to UniRec '%s'" ,
1567+ map_rec -> unirec .name );
1568+ return IPX_ERR_NOTFOUND ; // Do NOT add the record!
1569+ }
1570+
1571+ /* Internal "exporter_ip field" function
1572+ * Implemented as a special converter that must be enabled in the translator because
1573+ * IPFIX Message session is not defined in IPFIX record
1574+ */
1575+ if (src == MAP_SRC_INTERNAL_EXPORTER_IP ) {
1576+ if (trans -> extra_conv .exporter_ip .en ) {
1577+ // The function is already enabled!
1578+ IPX_CTX_ERROR (trans -> ctx , "Internal 'exporter_ip field' function can be mapped only "
1579+ "to one UniRec field!" , '\0' );
1580+ return IPX_ERR_DENIED ;
1581+ }
1582+
1583+ if (ur_type != UR_TYPE_IP ) {
1584+ IPX_CTX_ERROR (trans -> ctx , "Internal 'exporter_ip field' function supports only UniRec "
1585+ "ipaddress type but UniRec field '%s' is '%s'!" , map_rec -> unirec .name ,
1586+ map_rec -> unirec .type_str );
1587+ return IPX_ERR_DENIED ;
1588+ }
1589+
1590+ // Enable the internal converter
1591+ trans -> extra_conv .exporter_ip .en = true;
1592+ trans -> extra_conv .exporter_ip .req_idx = field_idx ;
1593+ trans -> extra_conv .exporter_ip .field_id = ur_id ;
1594+ IPX_CTX_DEBUG (trans -> ctx , "Added conversion from internal 'exporter_ip field' to UniRec '%s'" ,
1595+ map_rec -> unirec .name );
1596+ return IPX_ERR_NOTFOUND ; // Do NOT add the record!
1597+ }
1598+
14541599 IPX_CTX_ERROR (trans -> ctx , "Unimplemented internal mapping function!" , '\0' );
14551600 return IPX_ERR_DENIED ;
14561601}
@@ -1598,6 +1743,32 @@ translator_call_internals(translator_t *trans)
15981743 }
15991744 }
16001745
1746+ if (trans -> extra_conv .odid .en ) {
1747+ // Call internal 'odid field' converter
1748+ int field_idx = trans -> extra_conv .odid .req_idx ;
1749+ if (translate_internal_odid (trans ) == 0 ) {
1750+ // Success
1751+ trans -> progress .req_fields [field_idx ] = 0 ; // Filled!
1752+ converted_fields ++ ;
1753+ } else {
1754+ IPX_CTX_WARNING (trans -> ctx , "Internal function 'odid field' failed to fill "
1755+ "UniRec field '%s'" , trans -> progress .req_names [field_idx ]);
1756+ }
1757+ }
1758+
1759+ if (trans -> extra_conv .exporter_ip .en ) {
1760+ // Call internal 'exporter_ip field' converter
1761+ int field_idx = trans -> extra_conv .exporter_ip .req_idx ;
1762+ if (translate_internal_exporter_ip (trans ) == 0 ) {
1763+ // Success
1764+ trans -> progress .req_fields [field_idx ] = 0 ; // Filled!
1765+ converted_fields ++ ;
1766+ } else {
1767+ IPX_CTX_WARNING (trans -> ctx , "Internal function 'exporter_ip field' failed to fill "
1768+ "UniRec field '%s'" , trans -> progress .req_names [field_idx ]);
1769+ }
1770+ }
1771+
16011772 return converted_fields ;
16021773}
16031774
@@ -1634,9 +1805,9 @@ translator_destroy(translator_t *trans)
16341805}
16351806
16361807void
1637- translator_set_context (translator_t * trans , const struct fds_ipfix_msg_hdr * hdr )
1808+ translator_set_context (translator_t * trans , const struct ipx_msg_ctx * ctx )
16381809{
1639- trans -> msg_context .hdr = hdr ;
1810+ trans -> msg_context .ctx = ctx ;
16401811}
16411812
16421813const void *
0 commit comments