5252#include <errno.h>
5353#include <unistd.h>
5454#include <stdarg.h>
55+ #include <limits.h>
5556
5657/** Timeout configuration */
5758enum cfg_timeout_mode {
58- CFG_TIMEOUT_WAIT , /**< Block indefinitely */
59- CFG_TIMEOUT_NO_WAIT , /**< Don't block */
60- CFG_TIMEOUT_HALF_WAIT /**< Block only if some client is connected */
59+ CFG_TIMEOUT_WAIT = -1 , /**< Block indefinitely */
60+ CFG_TIMEOUT_NO_WAIT = -2 , /**< Don't block */
61+ CFG_TIMEOUT_HALF_WAIT = -3 /**< Block only if some client is connected */
6162};
6263
6364/** Default maximum number of connections over TCP/TCP-TLS/Unix */
@@ -76,41 +77,41 @@ struct ifc_common {
7677 /** Data buffering and sending in large bulks */
7778 bool buffer ;
7879 /** Timeout mode */
79- enum cfg_timeout_mode timeout ;
80+ long int timeout ;
8081};
8182
8283/*
8384 * <params>
8485 * <uniRecFormat>DST_IP,SRC_IP,BYTES,DST_PORT,?TCP_FLAGS,SRC_PORT,PROTOCOL</uniRecFormat>
8586 * <trapIfcCommon> <!-- optional -->
8687 * <timeout>NO_WAIT</timeout> <!-- optional -->
87- * <buffer>on </buffer> <!-- optional -->
88+ * <buffer>true </buffer> <!-- optional -->
8889 * <autoflush>500000</autoflush> <!-- optional -->
8990 * </trapIfcCommon>
9091 *
9192 * <trapIfcSpec>
9293 * <tcp>
9394 * <port>8000</port>
94- * <maxClients>64<maxClients> <!-- optional -->
95+ * <maxClients>64</ maxClients> <!-- optional -->
9596 * </tcp>
9697 * <tcp-tls>
9798 * <port>8000</port>
98- * <maxClients>64<maxClients> <!-- optional -->
99+ * <maxClients>64</ maxClients> <!-- optional -->
99100 * <keyFile>...</keyFile>
100101 * <certFile>...</certFile>
101102 * <caFile>...</caFile>
102103 * </tcp-tls>
103104 * <unix>
104105 * <name>ipfixcol-output</name>
105- * <maxClients>64<maxClients> <!-- optional -->
106+ * <maxClients>64</ maxClients> <!-- optional -->
106107 * </unix>
107108 * <file>
108109 * <name>/tmp/nemea/trapdata</name>
109110 * <mode>write</mode> <!-- optional -->
110111 * <time>0</time> <!-- optional -->
111112 * <size>0</size> <!-- optional -->
112113 * </file>
113- * <trapIfcSpec>
114+ * </ trapIfcSpec>
114115 * </params>
115116 */
116117
@@ -259,6 +260,40 @@ cfg_str_append(char **str, const char *fmt, ...)
259260 return IPX_OK ;
260261}
261262
263+ /**
264+ * \brief Convert a string to long integer
265+ *
266+ * If the string contains unexpected characters, conversion fails.
267+ * \param[in] str String to convert
268+ * \param[out] res Result
269+ * \return #IPX_OK on success
270+ * \return #IPX_ERR_FORMAT on failure
271+ */
272+ static int
273+ cfg_str2long (const char * str , long int * res )
274+ {
275+ if (strlen (str ) == 0 ) {
276+ // Empty string
277+ return IPX_ERR_FORMAT ;
278+ }
279+
280+ char * end_ptr = NULL ;
281+ errno = 0 ;
282+ long int tmp = strtol (str , & end_ptr , 10 );
283+ if ((errno == ERANGE || (tmp == LONG_MAX || tmp == LONG_MIN )) || (errno != 0 && tmp == 0 )) {
284+ // Conversion failure
285+ return IPX_ERR_FORMAT ;
286+ }
287+
288+ if (* end_ptr != '\0' ) {
289+ // Unexpected characters after the number
290+ return IPX_ERR_FORMAT ;
291+ }
292+
293+ * res = tmp ;
294+ return IPX_OK ;
295+ }
296+
262297/**
263298 * \brief Process \<trapIfcCommon\> node
264299 *
@@ -272,6 +307,8 @@ cfg_str_append(char **str, const char *fmt, ...)
272307static int
273308cfg_parse_common (ipx_ctx_t * ctx , fds_xml_ctx_t * root , struct ifc_common * common )
274309{
310+ long int val ;
311+
275312 const struct fds_xml_cont * content ;
276313 while (fds_xml_next (root , & content ) != FDS_EOC ) {
277314 switch (content -> id ) {
@@ -287,10 +324,12 @@ cfg_parse_common(ipx_ctx_t *ctx, fds_xml_ctx_t *root, struct ifc_common *common)
287324 assert (content -> type == FDS_OPTS_T_STRING );
288325 if (strcasecmp (content -> ptr_string , "wait" ) == 0 ) {
289326 common -> timeout = CFG_TIMEOUT_WAIT ;
290- } else if (strcasecmp (content -> ptr_string , "no-wait " ) == 0 ) {
327+ } else if (strcasecmp (content -> ptr_string , "no_wait " ) == 0 ) {
291328 common -> timeout = CFG_TIMEOUT_NO_WAIT ;
292- } else if (strcasecmp (content -> ptr_string , "half-wait " ) == 0 ) {
329+ } else if (strcasecmp (content -> ptr_string , "half_wait " ) == 0 ) {
293330 common -> timeout = CFG_TIMEOUT_HALF_WAIT ;
331+ } else if (cfg_str2long (content -> ptr_string , & val ) == IPX_OK && val > 0 ) {
332+ common -> timeout = val ;
294333 } else {
295334 IPX_CTX_ERROR (ctx , "Invalid interface timeout value '%s'" , content -> ptr_string );
296335 return IPX_ERR_FORMAT ;
@@ -617,6 +656,7 @@ cfg_parse_spec(ipx_ctx_t *ctx, fds_xml_ctx_t *root, struct conf_params *cfg)
617656static int
618657cfg_add_ifc_common (ipx_ctx_t * ctx , struct conf_params * cfg , const struct ifc_common * common )
619658{
659+ int rc ;
620660 char * * ptr = & cfg -> trap_ifc_spec ;
621661 assert ((* ptr ) != NULL );
622662
@@ -627,20 +667,26 @@ cfg_add_ifc_common(ipx_ctx_t *ctx, struct conf_params *cfg, const struct ifc_com
627667 }
628668
629669 // Add timeout parameter
630- const char * timeout_str = NULL ;
670+ const char * timeout_str ;
631671 switch (common -> timeout ) {
632672 case CFG_TIMEOUT_HALF_WAIT : timeout_str = "HALF_WAIT" ; break ;
633673 case CFG_TIMEOUT_NO_WAIT : timeout_str = "NO_WAIT" ; break ;
634674 case CFG_TIMEOUT_WAIT : timeout_str = "WAIT" ; break ;
675+ default : timeout_str = NULL ; break ;
676+ }
677+
678+ if (timeout_str == NULL ) {
679+ rc = cfg_str_append (ptr , ":timeout=%ld" , common -> timeout );
680+ } else {
681+ rc = cfg_str_append (ptr , ":timeout=%s" , timeout_str );
635682 }
636683
637- if (cfg_str_append ( ptr , ":timeout=%s" , timeout_str ) != IPX_OK ) {
684+ if (rc != IPX_OK ) {
638685 IPX_CTX_ERROR (ctx , "Unable to allocate memory (%s:%d)" , __FILE__ , __LINE__ );
639686 return IPX_ERR_NOMEM ;
640687 }
641688
642689 // Add autoflush parameter
643- int rc ;
644690 if (common -> autoflush == 0 ) {
645691 rc = cfg_str_append (ptr , ":autoflush=off" );
646692 } else {
0 commit comments