diff -crN 1/config.h.in 2/config.h.in *** 1/config.h.in 2010-02-19 20:48:17.000000000 +0300 --- 2/config.h.in 2010-03-11 14:45:51.127210783 +0300 *************** *** 37,42 **** --- 37,45 ---- /* Define to 1 if you have the `pfring' library (-lpfring). */ #undef HAVE_LIBPFRING + /* Define to 1 if you have the `pq' library (-lpq). */ + #undef HAVE_LIBPQ + /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD *************** *** 176,192 **** #undef VERSION /* Define for Solaris 2.5.1 so the uint32_t typedef from , ! , or is not used. If the typedef was allowed, the #define below would cause a syntax error. */ #undef _UINT32_T /* Define for Solaris 2.5.1 so the uint64_t typedef from , ! , or is not used. If the typedef was allowed, the #define below would cause a syntax error. */ #undef _UINT64_T /* Define for Solaris 2.5.1 so the uint8_t typedef from , ! , or is not used. If the typedef was allowed, the #define below would cause a syntax error. */ #undef _UINT8_T --- 179,195 ---- #undef VERSION /* Define for Solaris 2.5.1 so the uint32_t typedef from , ! , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT32_T /* Define for Solaris 2.5.1 so the uint64_t typedef from , ! , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT64_T /* Define for Solaris 2.5.1 so the uint8_t typedef from , ! , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT8_T diff -crN 1/configure 2/configure *** 1/configure 2010-02-19 20:48:16.000000000 +0300 --- 2/configure 2010-03-11 14:46:20.640210643 +0300 *************** *** 22,31 **** alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else ! case `(set -o) 2>/dev/null` in ! *posix*) set -o posix ;; esac - fi --- 22,33 ---- alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else ! case `(set -o) 2>/dev/null` in #( ! *posix*) : ! set -o posix ;; #( ! *) : ! ;; esac fi *************** *** 138,147 **** alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else ! case \`(set -o) 2>/dev/null\` in ! *posix*) set -o posix ;; esac - fi " as_required="as_fn_return () { (exit \$1); } --- 140,151 ---- alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else ! case \`(set -o) 2>/dev/null\` in #( ! *posix*) : ! set -o posix ;; #( ! *) : ! ;; esac fi " as_required="as_fn_return () { (exit \$1); } *************** *** 887,892 **** --- 891,897 ---- with_libpfring_libraries with_libpcap_includes with_libpcap_libraries + enable_pgsql enable_unittests enable_debug enable_nonbundled_htp *************** *** 1536,1541 **** --- 1541,1547 ---- --enable-ipfw Enable FreeBSD IPFW support for inline IDP --enable-prelude Enable Prelude support for alerts --enable-pfring Enable Native PF_RING support + --enable-pgsql Enable PostgreSQL database support --enable-unittests Enable compilation of the unit tests --enable-debug Enable debug output --enable-nonbundled-htp Enable the use of an already installed version of htp *************** *** 2061,2066 **** --- 2067,2195 ---- eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_type + + # ac_fn_c_find_intX_t LINENO BITS VAR + # ----------------------------------- + # Finds a signed integer type with width BITS, setting cache variable VAR + # accordingly. + ac_fn_c_find_intX_t () + { + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 + $as_echo_n "checking for int$2_t... " >&6; } + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 + else + eval "$3=no" + for ac_type in int$2_t 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + $ac_includes_default + int + main () + { + static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << ($2 - 2)) - 1) * 2 + 1))]; + test_array [0] = 0 + + ; + return 0; + } + _ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + $ac_includes_default + int + main () + { + static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << ($2 - 2)) - 1) * 2 + 1) + < ($ac_type) (((($ac_type) 1 << ($2 - 2)) - 1) * 2 + 2))]; + test_array [0] = 0 + + ; + return 0; + } + _ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + + else + case $ac_type in #( + int$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; + esac + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + eval as_val=\$$3 + if test "x$as_val" = x""no; then : + + else + break + fi + done + fi + eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 + $as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + + } # ac_fn_c_find_intX_t + + # ac_fn_c_find_uintX_t LINENO BITS VAR + # ------------------------------------ + # Finds an unsigned integer type with width BITS, setting cache variable VAR + # accordingly. + ac_fn_c_find_uintX_t () + { + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 + $as_echo_n "checking for uint$2_t... " >&6; } + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 + else + eval "$3=no" + for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + $ac_includes_default + int + main () + { + static int test_array [1 - 2 * !(($ac_type) -1 >> ($2 - 1) == 1)]; + test_array [0] = 0 + + ; + return 0; + } + _ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + case $ac_type in #( + uint$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; + esac + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + eval as_val=\$$3 + if test "x$as_val" = x""no; then : + + else + break + fi + done + fi + eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 + $as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + + } # ac_fn_c_find_uintX_t cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. *************** *** 3964,3982 **** while (*format) { switch (*format++) ! { ! case 's': // string ! str = va_arg (args_copy, const char *); ! break; ! case 'd': // int ! number = va_arg (args_copy, int); ! break; ! case 'f': // float ! fnumber = va_arg (args_copy, double); ! break; ! default: ! break; ! } } va_end (args_copy); va_end (args); --- 4093,4111 ---- while (*format) { switch (*format++) ! { ! case 's': // string ! str = va_arg (args_copy, const char *); ! break; ! case 'd': // int ! number = va_arg (args_copy, int); ! break; ! case 'f': // float ! fnumber = va_arg (args_copy, double); ! break; ! default: ! break; ! } } va_end (args_copy); va_end (args); *************** *** 3990,3996 **** _Bool success = false; // Check restrict. ! if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; --- 4119,4125 ---- _Bool success = false; // Check restrict. ! if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; *************** *** 4019,4025 **** // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' ! || dynamic_array[ni.number - 1] != 543); ; return 0; --- 4148,4154 ---- // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' ! || dynamic_array[ni.number - 1] != 543); ; return 0; *************** *** 4736,4748 **** else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext ! (eval echo "\"\$as_me:4739: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 ! (eval echo "\"\$as_me:4742: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 ! (eval echo "\"\$as_me:4745: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" --- 4865,4877 ---- else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext ! (eval echo "\"\$as_me:4868: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 ! (eval echo "\"\$as_me:4871: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 ! (eval echo "\"\$as_me:4874: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" *************** *** 5948,5954 **** ;; *-*-irix6*) # Find out which ABI we are using. ! echo '#line 5951 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? --- 6077,6083 ---- ;; *-*-irix6*) # Find out which ABI we are using. ! echo '#line 6080 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? *************** *** 7478,7488 **** -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` ! (eval echo "\"\$as_me:7481: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 ! echo "$as_me:7485: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. --- 7607,7617 ---- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` ! (eval echo "\"\$as_me:7610: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 ! echo "$as_me:7614: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. *************** *** 7817,7827 **** -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` ! (eval echo "\"\$as_me:7820: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 ! echo "$as_me:7824: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. --- 7946,7956 ---- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` ! (eval echo "\"\$as_me:7949: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 ! echo "$as_me:7953: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. *************** *** 7922,7932 **** -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` ! (eval echo "\"\$as_me:7925: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 ! echo "$as_me:7929: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized --- 8051,8061 ---- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` ! (eval echo "\"\$as_me:8054: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 ! echo "$as_me:8058: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized *************** *** 7977,7987 **** -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` ! (eval echo "\"\$as_me:7980: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 ! echo "$as_me:7984: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized --- 8106,8116 ---- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` ! (eval echo "\"\$as_me:8109: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 ! echo "$as_me:8113: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized *************** *** 10360,10366 **** lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF ! #line 10363 "configure" #include "confdefs.h" #if HAVE_DLFCN_H --- 10489,10495 ---- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF ! #line 10492 "configure" #include "confdefs.h" #if HAVE_DLFCN_H *************** *** 10456,10462 **** lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF ! #line 10459 "configure" #include "confdefs.h" #if HAVE_DLFCN_H --- 10585,10591 ---- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF ! #line 10588 "configure" #include "confdefs.h" #if HAVE_DLFCN_H *************** *** 11678,11738 **** fi ! ! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int32_t" >&5 ! $as_echo_n "checking for int32_t... " >&6; } ! if test "${ac_cv_c_int32_t+set}" = set; then : ! $as_echo_n "(cached) " >&6 ! else ! ac_cv_c_int32_t=no ! for ac_type in 'int32_t' 'int' 'long int' \ ! 'long long int' 'short int' 'signed char'; do ! cat confdefs.h - <<_ACEOF >conftest.$ac_ext ! /* end confdefs.h. */ ! $ac_includes_default ! int ! main () ! { ! static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1))]; ! test_array [0] = 0 ! ! ; ! return 0; ! } ! _ACEOF ! if ac_fn_c_try_compile "$LINENO"; then : ! cat confdefs.h - <<_ACEOF >conftest.$ac_ext ! /* end confdefs.h. */ ! $ac_includes_default ! int ! main () ! { ! static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1) ! < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 2))]; ! test_array [0] = 0 ! ! ; ! return 0; ! } ! _ACEOF ! if ac_fn_c_try_compile "$LINENO"; then : ! ! else ! case $ac_type in ! int32_t) ac_cv_c_int32_t=yes ;; ! *) ac_cv_c_int32_t=$ac_type ;; ! esac ! ! fi ! rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ! fi ! rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ! test "$ac_cv_c_int32_t" != no && break ! done ! fi ! { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_int32_t" >&5 ! $as_echo "$ac_cv_c_int32_t" >&6; } ! case $ac_cv_c_int32_t in #( no|yes) ;; #( *) --- 11807,11814 ---- fi ! ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" ! case $ac_cv_c_int32_t in #( no|yes) ;; #( *) *************** *** 11740,11783 **** #define int32_t $ac_cv_c_int32_t _ACEOF ;; - esac - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint16_t" >&5 - $as_echo_n "checking for uint16_t... " >&6; } - if test "${ac_cv_c_uint16_t+set}" = set; then : - $as_echo_n "(cached) " >&6 - else - ac_cv_c_uint16_t=no - for ac_type in 'uint16_t' 'unsigned int' 'unsigned long int' \ - 'unsigned long long int' 'unsigned short int' 'unsigned char'; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - $ac_includes_default - int - main () - { - static int test_array [1 - 2 * !(($ac_type) -1 >> (16 - 1) == 1)]; - test_array [0] = 0 - - ; - return 0; - } - _ACEOF - if ac_fn_c_try_compile "$LINENO"; then : - case $ac_type in - uint16_t) ac_cv_c_uint16_t=yes ;; - *) ac_cv_c_uint16_t=$ac_type ;; esac ! fi ! rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ! test "$ac_cv_c_uint16_t" != no && break ! done ! fi ! { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_uint16_t" >&5 ! $as_echo "$ac_cv_c_uint16_t" >&6; } ! case $ac_cv_c_uint16_t in #( no|yes) ;; #( *) --- 11816,11825 ---- #define int32_t $ac_cv_c_int32_t _ACEOF ;; esac ! ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" ! case $ac_cv_c_uint16_t in #( no|yes) ;; #( *) *************** *** 11788,11829 **** ;; esac ! ! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint32_t" >&5 ! $as_echo_n "checking for uint32_t... " >&6; } ! if test "${ac_cv_c_uint32_t+set}" = set; then : ! $as_echo_n "(cached) " >&6 ! else ! ac_cv_c_uint32_t=no ! for ac_type in 'uint32_t' 'unsigned int' 'unsigned long int' \ ! 'unsigned long long int' 'unsigned short int' 'unsigned char'; do ! cat confdefs.h - <<_ACEOF >conftest.$ac_ext ! /* end confdefs.h. */ ! $ac_includes_default ! int ! main () ! { ! static int test_array [1 - 2 * !(($ac_type) -1 >> (32 - 1) == 1)]; ! test_array [0] = 0 ! ! ; ! return 0; ! } ! _ACEOF ! if ac_fn_c_try_compile "$LINENO"; then : ! case $ac_type in ! uint32_t) ac_cv_c_uint32_t=yes ;; ! *) ac_cv_c_uint32_t=$ac_type ;; ! esac ! ! fi ! rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ! test "$ac_cv_c_uint32_t" != no && break ! done ! fi ! { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_uint32_t" >&5 ! $as_echo "$ac_cv_c_uint32_t" >&6; } ! case $ac_cv_c_uint32_t in #( no|yes) ;; #( *) --- 11830,11837 ---- ;; esac ! ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" ! case $ac_cv_c_uint32_t in #( no|yes) ;; #( *) *************** *** 11836,11877 **** ;; esac ! ! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint64_t" >&5 ! $as_echo_n "checking for uint64_t... " >&6; } ! if test "${ac_cv_c_uint64_t+set}" = set; then : ! $as_echo_n "(cached) " >&6 ! else ! ac_cv_c_uint64_t=no ! for ac_type in 'uint64_t' 'unsigned int' 'unsigned long int' \ ! 'unsigned long long int' 'unsigned short int' 'unsigned char'; do ! cat confdefs.h - <<_ACEOF >conftest.$ac_ext ! /* end confdefs.h. */ ! $ac_includes_default ! int ! main () ! { ! static int test_array [1 - 2 * !(($ac_type) -1 >> (64 - 1) == 1)]; ! test_array [0] = 0 ! ! ; ! return 0; ! } ! _ACEOF ! if ac_fn_c_try_compile "$LINENO"; then : ! case $ac_type in ! uint64_t) ac_cv_c_uint64_t=yes ;; ! *) ac_cv_c_uint64_t=$ac_type ;; ! esac ! ! fi ! rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ! test "$ac_cv_c_uint64_t" != no && break ! done ! fi ! { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_uint64_t" >&5 ! $as_echo "$ac_cv_c_uint64_t" >&6; } ! case $ac_cv_c_uint64_t in #( no|yes) ;; #( *) --- 11844,11851 ---- ;; esac ! ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" ! case $ac_cv_c_uint64_t in #( no|yes) ;; #( *) *************** *** 11884,11925 **** ;; esac ! ! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint8_t" >&5 ! $as_echo_n "checking for uint8_t... " >&6; } ! if test "${ac_cv_c_uint8_t+set}" = set; then : ! $as_echo_n "(cached) " >&6 ! else ! ac_cv_c_uint8_t=no ! for ac_type in 'uint8_t' 'unsigned int' 'unsigned long int' \ ! 'unsigned long long int' 'unsigned short int' 'unsigned char'; do ! cat confdefs.h - <<_ACEOF >conftest.$ac_ext ! /* end confdefs.h. */ ! $ac_includes_default ! int ! main () ! { ! static int test_array [1 - 2 * !(($ac_type) -1 >> (8 - 1) == 1)]; ! test_array [0] = 0 ! ! ; ! return 0; ! } ! _ACEOF ! if ac_fn_c_try_compile "$LINENO"; then : ! case $ac_type in ! uint8_t) ac_cv_c_uint8_t=yes ;; ! *) ac_cv_c_uint8_t=$ac_type ;; ! esac ! ! fi ! rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ! test "$ac_cv_c_uint8_t" != no && break ! done ! fi ! { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_uint8_t" >&5 ! $as_echo "$ac_cv_c_uint8_t" >&6; } ! case $ac_cv_c_uint8_t in #( no|yes) ;; #( *) --- 11858,11865 ---- ;; esac ! ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" ! case $ac_cv_c_uint8_t in #( no|yes) ;; #( *) *************** *** 13612,13617 **** --- 13552,13633 ---- fi LIBS="${TMPLIBS}" + #pgsql + # Check whether --enable-pgsql was given. + if test "${enable_pgsql+set}" = set; then : + enableval=$enable_pgsql; enable_pgsql=yes + + fi + + + if test "$enable_pgsql" = "yes"; then + CFLAGS="${CFLAGS} -D__SC_PGSQL_SUPPORT__" + fi + + ac_fn_c_check_header_mongrel "$LINENO" "libpq-fe.h" "ac_cv_header_libpq_fe_h" "$ac_includes_default" + if test "x$ac_cv_header_libpq_fe_h" = x""yes; then : + + else + as_fn_error "libpq-fe.h not found ..." "$LINENO" 5 + fi + + + + LIBPQ="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQconnectdb in -lpq" >&5 + $as_echo_n "checking for PQconnectdb in -lpq... " >&6; } + if test "${ac_cv_lib_pq_PQconnectdb+set}" = set; then : + $as_echo_n "(cached) " >&6 + else + ac_check_lib_save_LIBS=$LIBS + LIBS="-lpq $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + + /* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ + #ifdef __cplusplus + extern "C" + #endif + char PQconnectdb (); + int + main () + { + return PQconnectdb (); + ; + return 0; + } + _ACEOF + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pq_PQconnectdb=yes + else + ac_cv_lib_pq_PQconnectdb=no + fi + rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_check_lib_save_LIBS + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQconnectdb" >&5 + $as_echo "$ac_cv_lib_pq_PQconnectdb" >&6; } + if test "x$ac_cv_lib_pq_PQconnectdb" = x""yes; then : + cat >>confdefs.h <<_ACEOF + #define HAVE_LIBPQ 1 + _ACEOF + + LIBS="-lpq $LIBS" + + else + LIBPQ="no" + fi + + if test "$LIBPQ" = "no"; then + echo + echo " ERROR! libpq library not found" + echo + exit 1 + fi + # enable the running of unit tests # Check whether --enable-unittests was given. if test "${enable_unittests+set}" = set; then : *************** *** 14015,14024 **** alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else ! case `(set -o) 2>/dev/null` in ! *posix*) set -o posix ;; esac - fi --- 14031,14042 ---- alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else ! case `(set -o) 2>/dev/null` in #( ! *posix*) : ! set -o posix ;; #( ! *) : ! ;; esac fi diff -crN 1/configure.in 2/configure.in *** 1/configure.in 2010-02-19 20:47:52.000000000 +0300 --- 2/configure.in 2010-03-11 14:45:51.127210783 +0300 *************** *** 536,541 **** --- 536,562 ---- fi LIBS="${TMPLIBS}" + #pgsql + AC_ARG_ENABLE(pgsql, + [ --enable-pgsql Enable PostgreSQL database support], + [ enable_pgsql=yes + ]) + + if test "$enable_pgsql" = "yes"; then + CFLAGS="${CFLAGS} -D__SC_PGSQL_SUPPORT__" + fi + + AC_CHECK_HEADER(libpq-fe.h,,[AC_ERROR(libpq-fe.h not found ...)]) + + LIBPQ="" + AC_CHECK_LIB(pq, PQconnectdb,, LIBPQ="no") + if test "$LIBPQ" = "no"; then + echo + echo " ERROR! libpq library not found" + echo + exit 1 + fi + # enable the running of unit tests AC_ARG_ENABLE(unittests, [ --enable-unittests Enable compilation of the unit tests], diff -crN 1/src/alert-debuglog.c 2/src/alert-debuglog.c *** 1/src/alert-debuglog.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-debuglog.c 2010-03-11 14:45:51.115237392 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ /* alert debuglog *************** *** 39,45 **** TmEcode AlertDebugLogThreadInit(ThreadVars *, void*, void **); TmEcode AlertDebugLogThreadDeinit(ThreadVars *, void *); void AlertDebugLogExitPrintStats(ThreadVars *, void *); ! int AlertDebugLogOpenFileCtx(LogFileCtx* , const char *); void TmModuleAlertDebugLogRegister (void) { tmm_modules[TMM_ALERTDEBUGLOG].name = MODULE_NAME; --- 40,46 ---- TmEcode AlertDebugLogThreadInit(ThreadVars *, void*, void **); TmEcode AlertDebugLogThreadDeinit(ThreadVars *, void *); void AlertDebugLogExitPrintStats(ThreadVars *, void *); ! int AlertDebugLogOpenFileCtx(LogCtx* , const char *); void TmModuleAlertDebugLogRegister (void) { tmm_modules[TMM_ALERTDEBUGLOG].name = MODULE_NAME; *************** *** 53,63 **** } typedef struct AlertDebugLogThread_ { ! LogFileCtx *file_ctx; ! /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ } AlertDebugLogThread; ! static void CreateTimeString (const struct timeval *ts, char *str, size_t size) { time_t time = ts->tv_sec; struct tm *t = gmtime(&time); uint32_t sec = ts->tv_sec % 86400; --- 54,65 ---- } typedef struct AlertDebugLogThread_ { ! /** LogCtx has the pointer to the file and a mutex to allow multithreading */ ! LogCtx *l_ctx; } AlertDebugLogThread; ! static void CreateTimeString(const struct timeval *ts, char *str, size_t size) ! { time_t time = ts->tv_sec; struct tm *t = gmtime(&time); uint32_t sec = ts->tv_sec % 86400; *************** *** 79,135 **** CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); ! SCMutexLock(&aft->file_ctx->fp_mutex); ! fprintf(aft->file_ctx->fp, "+================\n"); ! fprintf(aft->file_ctx->fp, "TIME: %s\n", timebuf); ! fprintf(aft->file_ctx->fp, "ALERT CNT: %" PRIu32 "\n", p->alerts.cnt); for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; ! fprintf(aft->file_ctx->fp, "ALERT MSG [%02d]: %s\n", i, pa->msg); ! fprintf(aft->file_ctx->fp, "ALERT GID [%02d]: %" PRIu32 "\n", i, pa->gid); ! fprintf(aft->file_ctx->fp, "ALERT SID [%02d]: %" PRIu32 "\n", i, pa->sid); ! fprintf(aft->file_ctx->fp, "ALERT REV [%02d]: %" PRIu32 "\n", i, pa->rev); ! fprintf(aft->file_ctx->fp, "ALERT CLASS [%02d]: %s\n", i, pa->class_msg); ! fprintf(aft->file_ctx->fp, "ALERT PRIO [%02d]: %" PRIu32 "\n", i, pa->prio); } char srcip[16], dstip[16]; inet_ntop(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); ! fprintf(aft->file_ctx->fp, "SRC IP: %s\n", srcip); ! fprintf(aft->file_ctx->fp, "DST IP: %s\n", dstip); ! fprintf(aft->file_ctx->fp, "PROTO: %" PRIu32 "\n", IPV4_GET_IPPROTO(p)); if (IPV4_GET_IPPROTO(p) == IPPROTO_TCP || IPV4_GET_IPPROTO(p) == IPPROTO_UDP) { ! fprintf(aft->file_ctx->fp, "SRC PORT: %" PRIu32 "\n", p->sp); ! fprintf(aft->file_ctx->fp, "DST PORT: %" PRIu32 "\n", p->dp); } /* flow stuff */ ! fprintf(aft->file_ctx->fp, "FLOW: to_server: %s, to_client %s\n", p->flowflags & FLOW_PKT_TOSERVER ? "TRUE" : "FALSE", p->flowflags & FLOW_PKT_TOCLIENT ? "TRUE" : "FALSE"); PktVar *pv = PktVarGet(p,"http_host"); if (pv) { ! fprintf(aft->file_ctx->fp, "PKTVAR: %s\n", pv->name); ! PrintRawDataFp(aft->file_ctx->fp, pv->value, pv->value_len); } pv = PktVarGet(p,"http_ua"); if (pv) { ! fprintf(aft->file_ctx->fp, "PKTVAR: %s\n", pv->name); ! PrintRawDataFp(aft->file_ctx->fp, pv->value, pv->value_len); } for (i = 0; i < p->http_uri.cnt; i++) { ! fprintf(aft->file_ctx->fp, "RAW URI [%2d]: ", i); ! PrintRawUriFp(aft->file_ctx->fp, p->http_uri.raw[i], p->http_uri.raw_size[i]); ! fprintf(aft->file_ctx->fp, "\n"); ! PrintRawDataFp(aft->file_ctx->fp, p->http_uri.raw[i], p->http_uri.raw_size[i]); } /* any stuff */ --- 81,137 ---- CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); ! SCMutexLock(&aft->l_ctx->file.fp_mutex); ! fprintf(aft->l_ctx->file.fp, "+================\n"); ! fprintf(aft->l_ctx->file.fp, "TIME: %s\n", timebuf); ! fprintf(aft->l_ctx->file.fp, "ALERT CNT: %" PRIu32 "\n", p->alerts.cnt); for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; ! fprintf(aft->l_ctx->file.fp, "ALERT MSG [%02d]: %s\n", i, pa->msg); ! fprintf(aft->l_ctx->file.fp, "ALERT GID [%02d]: %" PRIu32 "\n", i, pa->gid); ! fprintf(aft->l_ctx->file.fp, "ALERT SID [%02d]: %" PRIu32 "\n", i, pa->sid); ! fprintf(aft->l_ctx->file.fp, "ALERT REV [%02d]: %" PRIu32 "\n", i, pa->rev); ! fprintf(aft->l_ctx->file.fp, "ALERT CLASS [%02d]: %s\n", i, pa->class_msg); ! fprintf(aft->l_ctx->file.fp, "ALERT PRIO [%02d]: %" PRIu32 "\n", i, pa->prio); } char srcip[16], dstip[16]; inet_ntop(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); ! fprintf(aft->l_ctx->file.fp, "SRC IP: %s\n", srcip); ! fprintf(aft->l_ctx->file.fp, "DST IP: %s\n", dstip); ! fprintf(aft->l_ctx->file.fp, "PROTO: %" PRIu32 "\n", IPV4_GET_IPPROTO(p)); if (IPV4_GET_IPPROTO(p) == IPPROTO_TCP || IPV4_GET_IPPROTO(p) == IPPROTO_UDP) { ! fprintf(aft->l_ctx->file.fp, "SRC PORT: %" PRIu32 "\n", p->sp); ! fprintf(aft->l_ctx->file.fp, "DST PORT: %" PRIu32 "\n", p->dp); } /* flow stuff */ ! fprintf(aft->l_ctx->file.fp, "FLOW: to_server: %s, to_client %s\n", p->flowflags & FLOW_PKT_TOSERVER ? "TRUE" : "FALSE", p->flowflags & FLOW_PKT_TOCLIENT ? "TRUE" : "FALSE"); PktVar *pv = PktVarGet(p,"http_host"); if (pv) { ! fprintf(aft->l_ctx->file.fp, "PKTVAR: %s\n", pv->name); ! PrintRawDataFp(aft->l_ctx->file.fp, pv->value, pv->value_len); } pv = PktVarGet(p,"http_ua"); if (pv) { ! fprintf(aft->l_ctx->file.fp, "PKTVAR: %s\n", pv->name); ! PrintRawDataFp(aft->l_ctx->file.fp, pv->value, pv->value_len); } for (i = 0; i < p->http_uri.cnt; i++) { ! fprintf(aft->l_ctx->file.fp, "RAW URI [%2d]: ", i); ! PrintRawUriFp(aft->l_ctx->file.fp, p->http_uri.raw[i], p->http_uri.raw_size[i]); ! fprintf(aft->l_ctx->file.fp, "\n"); ! PrintRawDataFp(aft->l_ctx->file.fp, p->http_uri.raw[i], p->http_uri.raw_size[i]); } /* any stuff */ *************** *** 137,150 **** /* pkt vars */ /* flowvars */ ! aft->file_ctx->alerts += p->alerts.cnt; ! fprintf(aft->file_ctx->fp, "PACKET LEN: %" PRIu32 "\n", p->pktlen); ! fprintf(aft->file_ctx->fp, "PACKET:\n"); ! PrintRawDataFp(aft->file_ctx->fp, p->pkt, p->pktlen); ! fflush(aft->file_ctx->fp); ! SCMutexUnlock(&aft->file_ctx->fp_mutex); return TM_ECODE_OK; } --- 139,152 ---- /* pkt vars */ /* flowvars */ ! aft->l_ctx->alerts += p->alerts.cnt; ! fprintf(aft->l_ctx->file.fp, "PACKET LEN: %" PRIu32 "\n", p->pktlen); ! fprintf(aft->l_ctx->file.fp, "PACKET:\n"); ! PrintRawDataFp(aft->l_ctx->file.fp, p->pkt, p->pktlen); ! fflush(aft->l_ctx->file.fp); ! SCMutexUnlock(&aft->l_ctx->file.fp_mutex); return TM_ECODE_OK; } *************** *** 158,168 **** if (p->alerts.cnt == 0) return TM_ECODE_OK; ! aft->file_ctx->alerts += p->alerts.cnt; CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); ! SCMutexLock(&aft->file_ctx->fp_mutex); for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; char srcip[46], dstip[46]; --- 160,170 ---- if (p->alerts.cnt == 0) return TM_ECODE_OK; ! aft->l_ctx->alerts += p->alerts.cnt; CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); ! SCMutexLock(&aft->l_ctx->file.fp_mutex); for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; char srcip[46], dstip[46]; *************** *** 170,185 **** inet_ntop(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); ! fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: fixme] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->prio, IPV6_GET_L4PROTO(p), srcip, p->sp, dstip, p->dp); } ! fflush(aft->file_ctx->fp); ! SCMutexUnlock(&aft->file_ctx->fp_mutex); return TM_ECODE_OK; } ! TmEcode AlertDebugLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { if (PKT_IS_IPV4(p)) { return AlertDebugLogIPv4(tv, p, data, pq); --- 172,187 ---- inet_ntop(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); ! fprintf(aft->l_ctx->file.fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: fixme] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->prio, IPV6_GET_L4PROTO(p), srcip, p->sp, dstip, p->dp); } ! fflush(aft->l_ctx->file.fp); ! SCMutexUnlock(&aft->l_ctx->file.fp_mutex); return TM_ECODE_OK; } ! TmEcode AlertDebugLog(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { if (PKT_IS_IPV4(p)) { return AlertDebugLogIPv4(tv, p, data, pq); *************** *** 193,211 **** TmEcode AlertDebugLogThreadInit(ThreadVars *t, void *initdata, void **data) { AlertDebugLogThread *aft = malloc(sizeof(AlertDebugLogThread)); ! if (aft == NULL) { return TM_ECODE_FAILED; - } memset(aft, 0, sizeof(AlertDebugLogThread)); ! if(initdata == NULL) ! { ! SCLogDebug("Error getting context for DebugLog. \"initdata\" argument NULL"); free(aft); return TM_ECODE_FAILED; } /** Use the Ouptut Context (file pointer and mutex) */ ! aft->file_ctx=(LogFileCtx *) initdata; *data = (void *)aft; return TM_ECODE_OK; --- 195,212 ---- TmEcode AlertDebugLogThreadInit(ThreadVars *t, void *initdata, void **data) { AlertDebugLogThread *aft = malloc(sizeof(AlertDebugLogThread)); ! if (!aft) return TM_ECODE_FAILED; memset(aft, 0, sizeof(AlertDebugLogThread)); ! if (!initdata) { ! SCLogDebug("Error getting context for DebugLog. \"initdata\" argument is NULL"); free(aft); return TM_ECODE_FAILED; } + /** Use the Ouptut Context (file pointer and mutex) */ ! aft->l_ctx = (LogCtx *)initdata; *data = (void *)aft; return TM_ECODE_OK; *************** *** 214,224 **** TmEcode AlertDebugLogThreadDeinit(ThreadVars *t, void *data) { AlertDebugLogThread *aft = (AlertDebugLogThread *)data; ! if (aft == NULL) { return TM_ECODE_OK; - } - - /* clear memory */ memset(aft, 0, sizeof(AlertDebugLogThread)); free(aft); --- 215,222 ---- TmEcode AlertDebugLogThreadDeinit(ThreadVars *t, void *data) { AlertDebugLogThread *aft = (AlertDebugLogThread *)data; ! if (!aft) return TM_ECODE_OK; memset(aft, 0, sizeof(AlertDebugLogThread)); free(aft); *************** *** 227,289 **** void AlertDebugLogExitPrintStats(ThreadVars *tv, void *data) { AlertDebugLogThread *aft = (AlertDebugLogThread *)data; ! if (aft == NULL) { return; - } ! SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, aft->file_ctx->alerts); } ! /** \brief Create a new LogFileCtx for alert debug logging. ! * \param ConfNode containing configuration for this logger. ! * \return NULL if failure, LogFileCtx* to the file_ctx if succesful ! * */ ! LogFileCtx *AlertDebugLogInitCtx(ConfNode *conf) { ! int ret=0; ! LogFileCtx* file_ctx=LogFileNewCtx(); ! ! if(file_ctx == NULL) ! { ! SCLogDebug("AlertDebugLogInitCtx: Couldn't create new file_ctx"); return NULL; } const char *filename = ConfNodeLookupChildValue(conf, "filename"); ! if (filename == NULL) filename = DEFAULT_LOG_FILENAME; ! /** fill the new LogFileCtx with the specific AlertDebugLog configuration */ ! ret=AlertDebugLogOpenFileCtx(file_ctx, filename); ! ! if(ret < 0) return NULL; ! return file_ctx; } ! /** \brief Read the config set the file pointer, open the file ! * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() ! * \param filename name of log file ! * \return -1 if failure, 0 if succesful ! * */ ! int AlertDebugLogOpenFileCtx(LogFileCtx *file_ctx, const char *filename) { - int ret=0; - char log_path[PATH_MAX], *log_dir; if (ConfGet("default-log-dir", &log_dir) != 1) log_dir = DEFAULT_LOG_DIR; ! snprintf(log_path, PATH_MAX, "%s/%s", log_dir, DEFAULT_LOG_FILENAME); ! file_ctx->fp = fopen(log_path, "w"); ! if (file_ctx->fp == NULL) { ! SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", log_path, ! strerror(errno)); return -1; } ! return ret; } - - --- 225,279 ---- void AlertDebugLogExitPrintStats(ThreadVars *tv, void *data) { AlertDebugLogThread *aft = (AlertDebugLogThread *)data; ! if (!aft) return; ! SCLogInfo("(%s) Alerts %" PRIu64, tv->name, aft->l_ctx->alerts); } ! /** ! * \brief Create a new LogCtx for alert debug logging. ! * \param ConfNode containing configuration for this logger. ! * \return NULL if failure, LogCtx pointer to the l_ctx if succesful ! */ ! LogCtx *AlertDebugLogInitCtx(ConfNode *conf) { ! LogCtx *l_ctx = LogNewCtx(); ! if (!l_ctx) { ! SCLogDebug("AlertDebugLogInitCtx: Could not create new output context"); return NULL; } const char *filename = ConfNodeLookupChildValue(conf, "filename"); ! if (!filename) filename = DEFAULT_LOG_FILENAME; ! /** fill the new LogCtx with the specific AlertDebugLog configuration */ ! if (AlertDebugLogOpenFileCtx(l_ctx, filename) < 0) return NULL; ! return l_ctx; } ! /** ! * \brief Read the config set the file pointer, open the file ! * \param l_ctx pointer to a created LogCtx using LogNewCtx() ! * \param filename name of log file ! * \return -1 if failure, 0 if succesful ! */ ! int AlertDebugLogOpenFileCtx(LogCtx *l_ctx, const char *filename) { char log_path[PATH_MAX], *log_dir; if (ConfGet("default-log-dir", &log_dir) != 1) log_dir = DEFAULT_LOG_DIR; ! snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); ! ! l_ctx->file.fp = fopen(log_path, "w"); ! if (!l_ctx->file.fp) { ! SCLogError(SC_ERR_FOPEN, "Failed to open %s: %s", log_path, strerror(errno)); return -1; } ! return 0; } diff -crN 1/src/alert-debuglog.h 2/src/alert-debuglog.h *** 1/src/alert-debuglog.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-debuglog.h 2010-03-11 14:45:50.874211411 +0300 *************** *** 1,12 **** /* Copyright (c) 2008 Victor Julien */ #ifndef __ALERT_DEBUGLOG_H__ #define __ALERT_DEBUGLOG_H__ ! void TmModuleAlertDebugLogRegister (void); ! void TmModuleAlertDebugLogIPv4Register (void); ! void TmModuleAlertDebugLogIPv6Register (void); ! LogFileCtx *AlertDebugLogInitCtx(ConfNode *); #endif /* __ALERT_DEBUGLOG_H__ */ --- 1,13 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ #ifndef __ALERT_DEBUGLOG_H__ #define __ALERT_DEBUGLOG_H__ ! void TmModuleAlertDebugLogRegister(void); ! void TmModuleAlertDebugLogIPv4Register(void); ! void TmModuleAlertDebugLogIPv6Register(void); ! LogCtx *AlertDebugLogInitCtx(ConfNode *); #endif /* __ALERT_DEBUGLOG_H__ */ diff -crN 1/src/alert-fastlog.c 2/src/alert-fastlog.c *** 1/src/alert-fastlog.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-fastlog.c 2010-03-11 14:45:50.410237392 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ /* alert fastlog *************** *** 47,53 **** TmEcode AlertFastLogThreadInit(ThreadVars *, void *, void **); TmEcode AlertFastLogThreadDeinit(ThreadVars *, void *); void AlertFastLogExitPrintStats(ThreadVars *, void *); ! int AlertFastLogOpenFileCtx(LogFileCtx *, const char *); void AlertFastLogRegisterTests(void); void TmModuleAlertFastLogRegister (void) { --- 48,54 ---- TmEcode AlertFastLogThreadInit(ThreadVars *, void *, void **); TmEcode AlertFastLogThreadDeinit(ThreadVars *, void *); void AlertFastLogExitPrintStats(ThreadVars *, void *); ! int AlertFastLogOpenFileCtx(LogCtx *, const char *); void AlertFastLogRegisterTests(void); void TmModuleAlertFastLogRegister (void) { *************** *** 80,90 **** } typedef struct AlertFastLogThread_ { ! /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ ! LogFileCtx* file_ctx; } AlertFastLogThread; ! static void CreateTimeString (const struct timeval *ts, char *str, size_t size) { time_t time = ts->tv_sec; struct tm *t = gmtime(&time); uint32_t sec = ts->tv_sec % 86400; --- 81,91 ---- } typedef struct AlertFastLogThread_ { ! /** LogCtx has the pointer to the file and a mutex to allow multithreading */ ! LogCtx* l_ctx; } AlertFastLogThread; ! static void CreateTimeString(const struct timeval *ts, char *str, size_t size) { time_t time = ts->tv_sec; struct tm *t = gmtime(&time); uint32_t sec = ts->tv_sec % 86400; *************** *** 106,114 **** CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); ! SCMutexLock(&aft->file_ctx->fp_mutex); ! aft->file_ctx->alerts += p->alerts.cnt; for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; --- 107,115 ---- CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); ! SCMutexLock(&aft->l_ctx->file.fp_mutex); ! aft->l_ctx->alerts += p->alerts.cnt; for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; *************** *** 118,128 **** inet_ntop(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); ! fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", ! timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp); ! fflush(aft->file_ctx->fp); } ! SCMutexUnlock(&aft->file_ctx->fp_mutex); return TM_ECODE_OK; } --- 119,130 ---- inet_ntop(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); ! fprintf(aft->l_ctx->file.fp, ! "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", ! timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp); } ! fflush(aft->l_ctx->file.fp); ! SCMutexUnlock(&aft->l_ctx->file.fp_mutex); return TM_ECODE_OK; } *************** *** 138,146 **** CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); ! SCMutexLock(&aft->file_ctx->fp_mutex); ! aft->file_ctx->alerts += p->alerts.cnt; for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; --- 140,148 ---- CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); ! SCMutexLock(&aft->l_ctx->file.fp_mutex); ! aft->l_ctx->alerts += p->alerts.cnt; for (i = 0; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; *************** *** 149,159 **** inet_ntop(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); ! fprintf(aft->file_ctx->fp, "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV6_GET_L4PROTO(p), srcip, p->sp, dstip, p->dp); } ! fflush(aft->file_ctx->fp); ! SCMutexUnlock(&aft->file_ctx->fp_mutex); return TM_ECODE_OK; } --- 151,162 ---- inet_ntop(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); inet_ntop(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); ! fprintf(aft->l_ctx->file.fp, ! "%s [**] [%" PRIu32 ":%" PRIu32 ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: %" PRIu32 "] {%" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV6_GET_L4PROTO(p), srcip, p->sp, dstip, p->dp); } ! fflush(aft->l_ctx->file.fp); ! SCMutexUnlock(&aft->l_ctx->file.fp_mutex); return TM_ECODE_OK; } *************** *** 172,259 **** TmEcode AlertFastLogThreadInit(ThreadVars *t, void *initdata, void **data) { AlertFastLogThread *aft = malloc(sizeof(AlertFastLogThread)); ! if (aft == NULL) { return TM_ECODE_FAILED; - } memset(aft, 0, sizeof(AlertFastLogThread)); ! if(initdata == NULL) ! { ! SCLogDebug("Error getting context for AlertFastLog. \"initdata\" argument NULL"); free(aft); return TM_ECODE_FAILED; } ! /** Use the Ouptut Context (file pointer and mutex) */ ! aft->file_ctx = (LogFileCtx*) initdata; *data = (void *)aft; return TM_ECODE_OK; } TmEcode AlertFastLogThreadDeinit(ThreadVars *t, void *data) { AlertFastLogThread *aft = (AlertFastLogThread *)data; ! if (aft == NULL) { return TM_ECODE_OK; - } /* clear memory */ ! memset(aft, 0, sizeof(AlertFastLogThread)); free(aft); return TM_ECODE_OK; } void AlertFastLogExitPrintStats(ThreadVars *tv, void *data) { AlertFastLogThread *aft = (AlertFastLogThread *)data; ! if (aft == NULL) { return; - } ! SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, aft->file_ctx->alerts); } /** ! * \brief Create a new LogFileCtx for "fast" output style. * \param conf The configuration node for this output. ! * \return A LogFileCtx pointer on success, NULL on failure. */ ! LogFileCtx *AlertFastLogInitCtx(ConfNode *conf) { ! LogFileCtx *logfile_ctx = LogFileNewCtx(); ! if (logfile_ctx == NULL) { ! SCLogDebug("AlertFastLogInitCtx2: Could not create new LogFileCtx"); return NULL; } const char *filename = ConfNodeLookupChildValue(conf, "filename"); ! if (filename == NULL) filename = DEFAULT_LOG_FILENAME; ! if (AlertFastLogOpenFileCtx(logfile_ctx, filename) < 0) { ! LogFileFreeCtx(logfile_ctx); return NULL; } SCLogInfo("Fast log output registered, filename: %s", filename); ! return logfile_ctx; } /** \brief Read the config set the file pointer, open the file ! * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() * \param filename name of log file * \return -1 if failure, 0 if succesful * */ ! int AlertFastLogOpenFileCtx(LogFileCtx *file_ctx, const char *filename) { char log_path[PATH_MAX], *log_dir; if (ConfGet("default-log-dir", &log_dir) != 1) log_dir = DEFAULT_LOG_DIR; snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); ! file_ctx->fp = fopen(log_path, "w"); ! ! if (file_ctx->fp == NULL) { ! SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", log_path, ! strerror(errno)); return -1; } --- 175,260 ---- TmEcode AlertFastLogThreadInit(ThreadVars *t, void *initdata, void **data) { AlertFastLogThread *aft = malloc(sizeof(AlertFastLogThread)); ! if (!aft) return TM_ECODE_FAILED; memset(aft, 0, sizeof(AlertFastLogThread)); ! ! if (!initdata) { ! SCLogDebug("Error getting context for AlertFastLog. \"initdata\" argument is NULL"); free(aft); return TM_ECODE_FAILED; } ! ! /** Use the output context (file pointer and mutex) */ ! aft->l_ctx = (LogCtx *)initdata; *data = (void *)aft; + return TM_ECODE_OK; } TmEcode AlertFastLogThreadDeinit(ThreadVars *t, void *data) { AlertFastLogThread *aft = (AlertFastLogThread *)data; ! if (!aft) return TM_ECODE_OK; /* clear memory */ ! //memset(aft, 0, sizeof(AlertFastLogThread)); // wtf? free(aft); + return TM_ECODE_OK; } void AlertFastLogExitPrintStats(ThreadVars *tv, void *data) { AlertFastLogThread *aft = (AlertFastLogThread *)data; ! if (!aft) return; ! SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, aft->l_ctx->alerts); } /** ! * \brief Create a new LogCtx for "fast" output style. * \param conf The configuration node for this output. ! * \return A LogCtx pointer on success, NULL on failure. */ ! LogCtx *AlertFastLogInitCtx(ConfNode *conf) { ! LogCtx *l_ctx = LogNewCtx(); ! if (!l_ctx) { ! SCLogDebug("AlertFastLogInitCtx: Could not create new LogCtx"); return NULL; } const char *filename = ConfNodeLookupChildValue(conf, "filename"); ! if (!filename) filename = DEFAULT_LOG_FILENAME; ! if (AlertFastLogOpenFileCtx(l_ctx, filename) < 0) { ! LogFreeCtx(l_ctx); return NULL; } SCLogInfo("Fast log output registered, filename: %s", filename); ! return l_ctx; } /** \brief Read the config set the file pointer, open the file ! * \param l_ctx pointer to a created LogCtx using LogNewCtx() * \param filename name of log file * \return -1 if failure, 0 if succesful * */ ! int AlertFastLogOpenFileCtx(LogCtx *l_ctx, const char *filename) { char log_path[PATH_MAX], *log_dir; if (ConfGet("default-log-dir", &log_dir) != 1) log_dir = DEFAULT_LOG_DIR; snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); ! l_ctx->file.fp = fopen(log_path, "w"); ! if (!l_ctx->file.fp) { ! SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", log_path, strerror(errno)); return -1; } diff -crN 1/src/alert-fastlog.h 2/src/alert-fastlog.h *** 1/src/alert-fastlog.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-fastlog.h 2010-03-11 14:45:50.671226078 +0300 *************** *** 1,13 **** /* Copyright (c) 2008 Victor Julien */ - #include "tm-modules.h" #ifndef __ALERT_FASTLOG_H__ #define __ALERT_FASTLOG_H__ void TmModuleAlertFastLogRegister (void); void TmModuleAlertFastLogIPv4Register (void); void TmModuleAlertFastLogIPv6Register (void); ! LogFileCtx *AlertFastLogInitCtx(ConfNode *); #endif /* __ALERT_FASTLOG_H__ */ --- 1,15 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ #ifndef __ALERT_FASTLOG_H__ #define __ALERT_FASTLOG_H__ + #include "tm-modules.h" + void TmModuleAlertFastLogRegister (void); void TmModuleAlertFastLogIPv4Register (void); void TmModuleAlertFastLogIPv6Register (void); ! LogCtx *AlertFastLogInitCtx(ConfNode *); #endif /* __ALERT_FASTLOG_H__ */ diff -crN 1/src/alert-pgsql-log.c 2/src/alert-pgsql-log.c *** 1/src/alert-pgsql-log.c 1970-01-01 03:00:00.000000000 +0300 --- 2/src/alert-pgsql-log.c 2010-03-11 20:43:03.916786262 +0300 *************** *** 0 **** --- 1,267 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ + + /** + * \file + * \author Andrew A. Usenok + * + * Logs alerts in PostgreSQL database + * + * \todo Delayed logging if database is unreachable + * \todo Unit testing + */ + + /* compile in, only if we have a PostgreSQL support */ + #ifdef __SC_PGSQL_SUPPORT__ + + #include + + #include + + #include "suricata-common.h" + #include "debug.h" + #include "detect.h" + #include "flow.h" + #include "conf.h" + + #include "threads.h" + #include "tm-threads.h" + #include "threadvars.h" + #include "tm-modules.h" + #include "util-debug.h" + + #include "output.h" + + #define DEFAULT_DB_NAME "suricata" + #define DEFAULT_TABLE_NAME "events" + + #define TABLE_STRUCT "time timestamp," \ + "gid integer," \ + "sid integer," \ + "rev smallint," \ + "msg varchar(128)," \ + "class_msg varchar(128)," \ + "prio smallint," \ + "proto smallint," \ + "srcip inet," \ + "srcport integer," \ + "dstip inet," \ + "dstport integer" + + #define MODULE_NAME "AlertPGSQLLog" + + LogCtx *AlertPGSQLLogInitCtx(ConfNode *); + int AlertPGSQLLogConnectDB(LogCtx *, const char *, const char *, const char *, const char *, const char *, const char *); + int AlertPGSQLLogCreateTable(LogCtx *, const char *); + TmEcode AlertPGSQLLogThreadInit(ThreadVars *, void *, void **); + TmEcode AlertPGSQLLog(ThreadVars *, Packet *, void *, PacketQueue *); + TmEcode AlertPGSQLLogThreadDeinit(ThreadVars *, void *); + void AlertPGSQLRegisterTests(void); + + void TmModuleAlertPGSQLLogRegister(void) { + tmm_modules[TMM_ALERTPGSQLLOG].name = MODULE_NAME; + tmm_modules[TMM_ALERTPGSQLLOG].ThreadInit = AlertPGSQLLogThreadInit; + tmm_modules[TMM_ALERTPGSQLLOG].Func = AlertPGSQLLog; + tmm_modules[TMM_ALERTPGSQLLOG].ThreadDeinit = AlertPGSQLLogThreadDeinit; + tmm_modules[TMM_ALERTPGSQLLOG].RegisterTests = AlertPGSQLRegisterTests; + + OutputRegisterModule(MODULE_NAME, "pgsql-log", AlertPGSQLLogInitCtx); + } + + typedef struct AlertPGSQLLogThread_ { + LogCtx* l_ctx; + } AlertPGSQLLogThread; + + static void CreateTimeString(const struct timeval *ts, char *str, size_t size) + { + time_t time = ts->tv_sec; + struct tm *t = gmtime(&time); + uint32_t sec = ts->tv_sec % 86400; + + snprintf(str, size, "%02u/%02u/%02u %02u:%02u:%02u.%06u", + t->tm_mon + 1, t->tm_mday, t->tm_year - 100, + sec / 3600, (sec % 3600) / 60, sec % 60, + (uint32_t)ts->tv_usec); + } + + /** + * \brief Create a new LogCtx for ouput in PostgreSQL. + * \param conf The configuration node for this output. + * \return A LogCtx pointer on success, NULL on failure. + */ + LogCtx *AlertPGSQLLogInitCtx(ConfNode *conf) + { + LogCtx *l_ctx = LogNewCtx(); + if (!l_ctx) { + SCLogDebug("AlertPGSQLLogInitCtx: Could not create new output context"); + return NULL; + } + + const char *host = ConfNodeLookupChildValue(conf, "host"); // default is to use local socket + const char *port = ConfNodeLookupChildValue(conf, "port"); // default is "5432" + const char *db_name = ConfNodeLookupChildValue(conf, "dbname"); + if (!db_name) + db_name = DEFAULT_DB_NAME; + const char *login = ConfNodeLookupChildValue(conf, "login"); // default is no authentication + const char *password = ConfNodeLookupChildValue(conf, "password"); + const char *table = ConfNodeLookupChildValue(conf, "table"); + if (!table) + table = DEFAULT_TABLE_NAME; + + SCLogDebug("AlertPGSQLLogInitCtx: host = \"%s\", port = \"%s\", db_name = \"%s\", login = \"%s\", password = \"%s\", table = \"%s\"", + host, port, db_name, login, password, table); + + if (AlertPGSQLLogConnectDB(l_ctx, host, port, db_name, login, password, table) < 0) { + LogFreeCtx(l_ctx); + return NULL; + } + + if (password) + memset((char *)password, 0, strlen(password)); // do not store password in memory + + SCLogInfo("PostgreSQL output registered, host: %s:%s, database: %s, login: %s", host, port, db_name, login); + + return l_ctx; + } + + /** + * \brief Connect to PostgreSQL database. + * \param logdb_ctx pointer to a created LogCtx using LogNewCtx(). + * \param host database server hostname + * \param port port number at server host + * \param db_name the database name + * \param login user name to connect as + * \param password user password + * \return -1 if failure, 0 if succesful + */ + int AlertPGSQLLogConnectDB(LogCtx *l_ctx, const char *host, const char *port, const char *db_name, const char *login, const char *password, const char *table) + { + PGconn *conn = PQsetdbLogin(host, port, NULL, NULL, db_name, login, password); + if (PQstatus(conn) == CONNECTION_BAD) { + SCLogError(SC_ERR_PGSQL_LOG_GENERIC, "%s", PQerrorMessage(conn)); + return -1; + } else + SCLogInfo("AlertPGSQLLogConnectDB: Succesfully connected to database"); + + // Set apropriate verbosity level + PQsetErrorVerbosity(conn, PQERRORS_TERSE); + + // Set context + l_ctx->db.pgconn = conn; + l_ctx->db.host = (host) ? strdup(host) : NULL; + l_ctx->db.port = (port) ? strdup(port) : NULL; + l_ctx->db.db_name = strdup(db_name); + l_ctx->db.login = (login) ? strdup(login) : NULL; + + // Create table if not exists + if (AlertPGSQLLogCreateTable(l_ctx, table) < 0) + return -1; + + return 0; + } + + int AlertPGSQLLogCreateTable(LogCtx *l_ctx, const char *table) + { + PGresult *res; + char query[400]; + + snprintf(query, 400, "CREATE TABLE %s(" TABLE_STRUCT ")", table); + res = PQexec(l_ctx->db.pgconn, query); + if (!res) { + SCLogError(SC_ERR_PGSQL_LOG_GENERIC, "%s", PQresultErrorMessage(res)); + return -1; + } + + if (PQresultStatus(res) == PGRES_COMMAND_OK) + SCLogInfo("AlertPGSQLLogCreateTable: Table succesfully created"); + else + SCLogInfo("AlertPGSQLLogCreateTable: Table already exists"); + + l_ctx->db.table = strdup(table); + + PQclear(res); + + return 0; + } + + TmEcode AlertPGSQLLogThreadInit(ThreadVars *t, void *initdata, void **data) + { + AlertPGSQLLogThread *apt = malloc(sizeof(AlertPGSQLLogThread)); + if (!apt) + return TM_ECODE_FAILED; + + memset(apt, 0, sizeof(AlertPGSQLLogThread)); + + if (!initdata) { + SCLogDebug("AlertPGSQLLogThreadInit: Error getting context for AlertPGSQLLog. \"initdata\" argument is NULL"); + free(apt); + return TM_ECODE_FAILED; + } + + apt->l_ctx = (LogCtx *)initdata; + *data = (void *)apt; + + return TM_ECODE_OK; + } + + TmEcode AlertPGSQLLogThreadDeinit(ThreadVars *t, void *data) + { + AlertPGSQLLogThread *apt = (AlertPGSQLLogThread *)data; + if (apt) { + /* close connection to database */ + PQfinish(apt->l_ctx->db.pgconn); + + /* free memory */ + free(apt); + } + + return TM_ECODE_OK; + } + + TmEcode AlertPGSQLLog(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) + { + AlertPGSQLLogThread *apt = (AlertPGSQLLogThread *)data; + PacketAlert *pa; + PGresult *res; + char query[400], + timebuf[64], + srcip[46], + dstip[46]; + int i; + + if (p->alerts.cnt == 0) + return TM_ECODE_OK; + + CreateTimeString(&p->ts, timebuf, sizeof(timebuf)); + + for (i = 0; i < p->alerts.cnt; i++) { + pa = &p->alerts.alerts[i]; + + if (PKT_IS_IPV4(p)) { + inet_ntop(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip)); + inet_ntop(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip)); + } else if (PKT_IS_IPV6(p)) { + inet_ntop(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip)); + inet_ntop(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip)); + } + + snprintf(query, 400, "INSERT INTO %s VALUES ('%s', %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", '%s', '%s', %" PRIu32 ", %" PRIu32 ", '%s', %" PRIu32 ", '%s', %" PRIu32 ")", + apt->l_ctx->db.table, timebuf, pa->gid, pa->sid, pa->rev, pa->msg, pa->class_msg, pa->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp); + res = PQexec(apt->l_ctx->db.pgconn, query); + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { + SCLogDebug("AlertPGSQLLog: %s", PQresultErrorMessage(res)); + return TM_ECODE_FAILED; + } + } + + PQclear(res); + + return TM_ECODE_OK; + } + + void AlertPGSQLRegisterTests(void) { + #ifdef UNITTESTS + #endif /* UNITTESTS */ + } + + #endif /* __SC_PGSQL_SUPPORT__ */ + diff -crN 1/src/alert-pgsql-log.h 2/src/alert-pgsql-log.h *** 1/src/alert-pgsql-log.h 1970-01-01 03:00:00.000000000 +0300 --- 2/src/alert-pgsql-log.h 2010-03-11 14:45:51.103237462 +0300 *************** *** 0 **** --- 1,14 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ + + #ifndef __ALERT_PGSQL_LOG_H__ + #define __ALERT_PGSQL_LOG_H__ + + /* compile in, only if we have a PostgreSQL support */ + #ifdef __SC_PGSQL_SUPPORT__ + + void TmModuleAlertPGSQLLogRegister(void); + LogCtx *AlertPGSQLLogInitCtx(ConfNode *); + + #endif /* __SC_PGSQL_SUPPORT__ */ + + #endif /* __ALERT_PGSQL_LOG_H__ */ diff -crN 1/src/alert-prelude.c 2/src/alert-prelude.c *** 1/src/alert-prelude.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-prelude.c 2010-03-11 14:45:50.745229919 +0300 *************** *** 1,5 **** ! /* Copyright (c) 2010 Pierre Chifflier ! * * Some code borrowed from snort's prelude output plugin, originally * written by Yoann Vandoorselaere */ --- 1,5 ---- ! /* Copyright (c) 2010 Andrew A. Usenok ! * Copyright (c) 2010 Pierre Chifflier * Some code borrowed from snort's prelude output plugin, originally * written by Yoann Vandoorselaere */ *************** *** 40,53 **** #include "output.h" #ifndef PRELUDE ! /** Handle the case where no PRELUDE support is compiled in. ! * */ TmEcode AlertPrelude (ThreadVars *, Packet *, void *, PacketQueue *); TmEcode AlertPreludeThreadInit(ThreadVars *, void *, void **); TmEcode AlertPreludeThreadDeinit(ThreadVars *, void *); ! int AlertPreludeOpenFileCtx(LogFileCtx *, char *); void AlertPreludeRegisterTests(void); void TmModuleAlertPreludeRegister (void) { --- 40,53 ---- #include "output.h" #ifndef PRELUDE ! /** ! * Handle the case where no PRELUDE support is compiled in. */ TmEcode AlertPrelude (ThreadVars *, Packet *, void *, PacketQueue *); TmEcode AlertPreludeThreadInit(ThreadVars *, void *, void **); TmEcode AlertPreludeThreadDeinit(ThreadVars *, void *); ! int AlertPreludeOpenFileCtx(LogCtx *, char *); void AlertPreludeRegisterTests(void); void TmModuleAlertPreludeRegister (void) { *************** *** 58,76 **** tmm_modules[TMM_ALERTPRELUDE].RegisterTests = AlertPreludeRegisterTests; } ! LogFileCtx *AlertPreludeInitCtx(ConfNode *conf) { ! SCLogDebug("Can't init Prelude output - Prelude support was disabled during build."); return NULL; } TmEcode AlertPreludeThreadInit(ThreadVars *t, void *initdata, void **data) { ! SCLogDebug("Can't init Prelude output thread - Prelude support was disabled during build."); return TM_ECODE_FAILED; } ! TmEcode AlertPrelude (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { return TM_ECODE_OK; } --- 58,76 ---- tmm_modules[TMM_ALERTPRELUDE].RegisterTests = AlertPreludeRegisterTests; } ! LogCtx *AlertPreludeInitCtx(ConfNode *conf) { ! SCLogDebug("Can't init Prelude output - Prelude support was disabled during build"); return NULL; } TmEcode AlertPreludeThreadInit(ThreadVars *t, void *initdata, void **data) { ! SCLogDebug("Can't init Prelude output thread - Prelude support was disabled during build"); return TM_ECODE_FAILED; } ! TmEcode AlertPrelude(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { return TM_ECODE_OK; } *************** *** 80,86 **** return TM_ECODE_FAILED; } ! void AlertPreludeRegisterTests (void) { } #else /* implied we do have PRELUDE support */ --- 80,86 ---- return TM_ECODE_FAILED; } ! void AlertPreludeRegisterTests(void) { } #else /* implied we do have PRELUDE support */ *************** *** 103,113 **** static unsigned int mid_priority = 2; ! LogFileCtx *AlertPreludeInitCtx(ConfNode *conf); ! TmEcode AlertPrelude (ThreadVars *, Packet *, void *, PacketQueue *); TmEcode AlertPreludeThreadInit(ThreadVars *, void *, void **); TmEcode AlertPreludeThreadDeinit(ThreadVars *, void *); ! int AlertPreludeOpenFileCtx(LogFileCtx *, char *); void AlertPreludeRegisterTests(void); void TmModuleAlertPreludeRegister (void) { --- 103,113 ---- static unsigned int mid_priority = 2; ! LogCtx *AlertPreludeInitCtx(ConfNode *conf); ! TmEcode AlertPrelude(ThreadVars *, Packet *, void *, PacketQueue *); TmEcode AlertPreludeThreadInit(ThreadVars *, void *, void **); TmEcode AlertPreludeThreadDeinit(ThreadVars *, void *); ! int AlertPreludeOpenFileCtx(LogCtx *, char *); void AlertPreludeRegisterTests(void); void TmModuleAlertPreludeRegister (void) { *************** *** 759,765 **** * * \return A newly allocated AlertPreludeCtx structure, or NULL */ ! LogFileCtx *AlertPreludeInitCtx(ConfNode *conf) { int ret; prelude_client_t *client; --- 759,765 ---- * * \return A newly allocated AlertPreludeCtx structure, or NULL */ ! LogCtx *AlertPreludeInitCtx(ConfNode *conf) { int ret; prelude_client_t *client; diff -crN 1/src/alert-prelude.h 2/src/alert-prelude.h *** 1/src/alert-prelude.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-prelude.h 2010-03-11 14:45:50.339237253 +0300 *************** *** 1,9 **** /* Copyright (c) 2010 Pierre Chifflier */ #ifndef __ALERT_PRELUDE_H__ #define __ALERT_PRELUDE_H__ void TmModuleAlertPreludeRegister (void); ! LogFileCtx *AlertPreludeInitCtx(ConfNode *conf); #endif /* __ALERT_PRELUDE_H__ */ --- 1,10 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2010 Pierre Chifflier */ #ifndef __ALERT_PRELUDE_H__ #define __ALERT_PRELUDE_H__ void TmModuleAlertPreludeRegister (void); ! LogCtx *AlertPreludeInitCtx(ConfNode *conf); #endif /* __ALERT_PRELUDE_H__ */ diff -crN 1/src/alert-unified2-alert.c 2/src/alert-unified2-alert.c *** 1/src/alert-unified2-alert.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-unified2-alert.c 2010-03-11 14:45:51.115237392 +0300 *************** *** 1,7 **** /* Copyright (c) 2009 Open Information Security Foundation */ ! /** \file ! * \author Breno Silva */ #include "suricata-common.h" --- 1,9 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2009 Open Information Security Foundation */ ! /** ! * \file ! * \author Breno Silva */ #include "suricata-common.h" *************** *** 38,52 **** /**< Minimum log file limit in MB. */ #define MIN_LIMIT 1 - /*prototypes*/ TmEcode Unified2Alert (ThreadVars *, Packet *, void *, PacketQueue *); TmEcode Unified2AlertThreadInit(ThreadVars *, void *, void **); TmEcode Unified2AlertThreadDeinit(ThreadVars *, void *); int Unified2IPv4TypeAlert(ThreadVars *, Packet *, void *, PacketQueue *); int Unified2IPv6TypeAlert(ThreadVars *, Packet *, void *, PacketQueue *); int Unified2PacketTypeAlert(ThreadVars *, Packet *, void *); ! void Unified2RegisterTests(); ! int Unified2AlertOpenFileCtx(LogFileCtx *, const char *); /** * Unified2 thread vars --- 40,53 ---- /**< Minimum log file limit in MB. */ #define MIN_LIMIT 1 TmEcode Unified2Alert (ThreadVars *, Packet *, void *, PacketQueue *); TmEcode Unified2AlertThreadInit(ThreadVars *, void *, void **); TmEcode Unified2AlertThreadDeinit(ThreadVars *, void *); int Unified2IPv4TypeAlert(ThreadVars *, Packet *, void *, PacketQueue *); int Unified2IPv6TypeAlert(ThreadVars *, Packet *, void *, PacketQueue *); int Unified2PacketTypeAlert(ThreadVars *, Packet *, void *); ! void Unified2RegisterTests(void); ! int Unified2AlertOpenFileCtx(LogCtx *, const char *); /** * Unified2 thread vars *************** *** 54,60 **** * Used for storing file options. */ typedef struct Unified2AlertThread_ { ! LogFileCtx *file_ctx; /** LogFileCtx pointer */ } Unified2AlertThread; /** --- 55,61 ---- * Used for storing file options. */ typedef struct Unified2AlertThread_ { ! LogCtx *l_ctx; } Unified2AlertThread; /** *************** *** 142,236 **** } /** ! * \brief Function to close unified2 file * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param aun Unified2 thread variable. */ int Unified2AlertCloseFile(ThreadVars *t, Unified2AlertThread *aun) { ! if (aun->file_ctx->fp != NULL) { ! fclose(aun->file_ctx->fp); } ! aun->file_ctx->size_current = 0; return 0; } /** ! * \brief Function to rotate unified2 file * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param aun Unified2 thread variable. ! * \retval 0 on succces ! * \retval -1 on failure */ int Unified2AlertRotateFile(ThreadVars *t, Unified2AlertThread *aun) { ! if (Unified2AlertCloseFile(t,aun) < 0) { ! SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, ! "Error: Unified2AlertCloseFile failed"); return -1; } ! if (Unified2AlertOpenFileCtx(aun->file_ctx,aun->file_ctx->prefix) < 0) { ! SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, ! "Error: Unified2AlertOpenFileCtx, open new log file failed"); return -1; } return 0; } ! TmEcode Unified2Alert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq) { int ret = 0; ! if(PKT_IS_IPV4(p)) { ! ret = Unified2IPv4TypeAlert (t, p, data, pq); ! }else if(PKT_IS_IPV6(p)) { ! ret = Unified2IPv6TypeAlert (t, p, data, pq); } else { /* we're only supporting IPv4 and IPv6 */ ! return TM_ECODE_OK; } ! if (ret) ! return TM_ECODE_FAILED; ! ! return TM_ECODE_OK; } /** ! * \brief Function to fill unified2 packet format into the file. * No need to lock here, since it's already locked * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param p Packet struct used to decide for ipv4 or ipv6 ! * \param data Unified2 thread data. ! * \retval 0 on succces ! * \retval -1 on failure */ ! int Unified2PacketTypeAlert (ThreadVars *t, Packet *p, void *data) { Unified2AlertThread *aun = (Unified2AlertThread *)data; Unified2Packet phdr; Unified2AlertFileHeader hdr; ! int ret, len; char write_buffer[sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) + IPV4_MAXPACKET_LEN]; ! if(p->pktlen > 0) len = (sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet)) - 4 + p->pktlen; else len = (sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet)) - 4; ! memset(write_buffer,0,sizeof(write_buffer)); memset(&hdr, 0, sizeof(Unified2AlertFileHeader)); memset(&phdr, 0, sizeof(Unified2Packet)); hdr.type = htonl(UNIFIED2_PACKET_TYPE); ! hdr.length = htonl(sizeof(Unified2Packet) -4 + p->pktlen); ! memcpy(write_buffer,&hdr,sizeof(Unified2AlertFileHeader)); phdr.sensor_id = 0; phdr.linktype = htonl(p->datalink); --- 143,232 ---- } /** ! * \brief Function to close unified2 file * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param aun Unified2 thread variable. */ int Unified2AlertCloseFile(ThreadVars *t, Unified2AlertThread *aun) { ! if (aun->l_ctx->file.fp) { ! fclose(aun->l_ctx->file.fp); } ! aun->l_ctx->file.size_current = 0; return 0; } /** ! * \brief Function to rotate unified2 file * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param aun Unified2 thread variable. ! * \retval 0 on succces ! * \retval -1 on failure */ int Unified2AlertRotateFile(ThreadVars *t, Unified2AlertThread *aun) { ! if (Unified2AlertCloseFile(t, aun) < 0) { ! SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Unified2AlertCloseFile failed"); return -1; } ! if (Unified2AlertOpenFileCtx(aun->l_ctx, aun->l_ctx->file.prefix) < 0) { ! SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Unified2AlertOpenFileCtx, open new log file failed"); return -1; } return 0; } ! TmEcode Unified2Alert(ThreadVars *t, Packet *p, void *data, PacketQueue *pq) { int ret = 0; ! if (PKT_IS_IPV4(p)) { ! ret = Unified2IPv4TypeAlert(t, p, data, pq); ! } else if(PKT_IS_IPV6(p)) { ! ret = Unified2IPv6TypeAlert(t, p, data, pq); } else { /* we're only supporting IPv4 and IPv6 */ ! ret = TM_ECODE_OK; } ! return ret; } /** ! * \brief Function to fill unified2 packet format into the file. * No need to lock here, since it's already locked * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param p Packet struct used to decide for ipv4 or ipv6 ! * \param data Unified2 thread data. ! * \retval 0 on succces ! * \retval -1 on failure */ ! int Unified2PacketTypeAlert(ThreadVars *t, Packet *p, void *data) { Unified2AlertThread *aun = (Unified2AlertThread *)data; Unified2Packet phdr; Unified2AlertFileHeader hdr; ! int len; char write_buffer[sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) + IPV4_MAXPACKET_LEN]; ! if (p->pktlen > 0) len = (sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet)) - 4 + p->pktlen; else len = (sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet)) - 4; ! memset(write_buffer, 0, sizeof(write_buffer)); memset(&hdr, 0, sizeof(Unified2AlertFileHeader)); memset(&phdr, 0, sizeof(Unified2Packet)); hdr.type = htonl(UNIFIED2_PACKET_TYPE); ! hdr.length = htonl(sizeof(Unified2Packet) - 4 + p->pktlen); ! memcpy(write_buffer, &hdr, sizeof(Unified2AlertFileHeader)); phdr.sensor_id = 0; phdr.linktype = htonl(p->datalink); *************** *** 239,266 **** phdr.packet_microsecond = htonl(p->ts.tv_usec); phdr.packet_length = htonl(p->pktlen); ! memcpy(write_buffer+sizeof(Unified2AlertFileHeader),&phdr,sizeof(Unified2Packet) - 4); ! memcpy(write_buffer + sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) - 4 , p->pkt, p->pktlen); ! ret = fwrite(write_buffer,len, 1, aun->file_ctx->fp); ! if (ret != 1) { ! SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno)); return -1; } ! aun->file_ctx->size_current += len; return 0; } /** ! * \brief Function to fill unified2 ipv6 ids type format into the file. * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param p Packet struct used to decide for ipv4 or ipv6 ! * \param data Unified2 thread data. ! * \param pq Packet queue ! * \retval 0 on succces ! * \retval -1 on failure */ int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq) --- 235,261 ---- phdr.packet_microsecond = htonl(p->ts.tv_usec); phdr.packet_length = htonl(p->pktlen); ! memcpy(write_buffer + sizeof(Unified2AlertFileHeader), &phdr, sizeof(Unified2Packet) - 4); ! memcpy(write_buffer + sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) - 4, p->pkt, p->pktlen); ! if (fwrite(write_buffer,len, 1, aun->l_ctx->file.fp) != 1) { ! SCLogError(SC_ERR_FWRITE, "write failed: %s", strerror(errno)); return -1; } ! aun->l_ctx->file.size_current += len; return 0; } /** ! * \brief Function to fill unified2 ipv6 ids type format into the file. * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param p Packet struct used to decide for ipv4 or ipv6 ! * \param data Unified2 thread data. ! * \param pq Packet queue ! * \retval 0 on succces ! * \retval -1 on failure */ int Unified2IPv6TypeAlert (ThreadVars *t, Packet *p, void *data, PacketQueue *pq) *************** *** 270,276 **** Unified2AlertFileHeader hdr; PacketAlert *pa; uint8_t ethh_offset = 0; ! int ret, len; char write_buffer[sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv6Unified2)]; if (p->alerts.cnt == 0) --- 265,271 ---- Unified2AlertFileHeader hdr; PacketAlert *pa; uint8_t ethh_offset = 0; ! int len; char write_buffer[sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv6Unified2)]; if (p->alerts.cnt == 0) *************** *** 278,284 **** len = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv6Unified2)); ! memset(write_buffer,0,sizeof(write_buffer)); memset(&hdr, 0, sizeof(Unified2AlertFileHeader)); memset(&phdr, 0, sizeof(AlertIPv6Unified2)); --- 273,279 ---- len = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv6Unified2)); ! memset(write_buffer, 0, sizeof(write_buffer)); memset(&hdr, 0, sizeof(Unified2AlertFileHeader)); memset(&phdr, 0, sizeof(AlertIPv6Unified2)); *************** *** 286,317 **** hdr.type = htonl(UNIFIED2_IDS_EVENT_IPV6_TYPE); hdr.length = htonl(sizeof(AlertIPv6Unified2)); ! memcpy(write_buffer,&hdr,sizeof(Unified2AlertFileHeader)); /* if we have no ethernet header (e.g. when using nfq), we have to create * one ourselves. */ ! if (p->ethh == NULL) { ethh_offset = sizeof(EthernetHdr); } /* fill the phdr structure with the data of the packet */ - phdr.sensor_id = 0; phdr.event_id = 0; phdr.event_second = htonl(p->ts.tv_sec); phdr.event_microsecond = htonl(p->ts.tv_usec); ! phdr.src_ip = *(struct in6_addr*)GET_IPV6_SRC_ADDR(p); ! phdr.dst_ip = *(struct in6_addr*)GET_IPV6_DST_ADDR(p); phdr.protocol = IPV6_GET_NH(p); ! if(p->action & ACTION_DROP) phdr.packet_action = UNIFIED2_BLOCKED_FLAG; else phdr.packet_action = 0; ! switch(phdr.protocol) { case IPPROTO_ICMPV6: ! if(p->icmpv6h) { phdr.sp = htons(p->icmpv6h->type); phdr.dp = htons(p->icmpv6h->code); } else { --- 281,311 ---- hdr.type = htonl(UNIFIED2_IDS_EVENT_IPV6_TYPE); hdr.length = htonl(sizeof(AlertIPv6Unified2)); ! memcpy(write_buffer, &hdr, sizeof(Unified2AlertFileHeader)); /* if we have no ethernet header (e.g. when using nfq), we have to create * one ourselves. */ ! if (!p->ethh) { ethh_offset = sizeof(EthernetHdr); } /* fill the phdr structure with the data of the packet */ phdr.sensor_id = 0; phdr.event_id = 0; phdr.event_second = htonl(p->ts.tv_sec); phdr.event_microsecond = htonl(p->ts.tv_usec); ! phdr.src_ip = *(struct in6_addr *)GET_IPV6_SRC_ADDR(p); ! phdr.dst_ip = *(struct in6_addr *)GET_IPV6_DST_ADDR(p); phdr.protocol = IPV6_GET_NH(p); ! if (p->action & ACTION_DROP) phdr.packet_action = UNIFIED2_BLOCKED_FLAG; else phdr.packet_action = 0; ! switch (phdr.protocol) { case IPPROTO_ICMPV6: ! if (p->icmpv6h) { phdr.sp = htons(p->icmpv6h->type); phdr.dp = htons(p->icmpv6h->code); } else { *************** *** 320,326 **** } break; case IPPROTO_ICMP: ! if(p->icmpv4h) { phdr.sp = htons(p->icmpv4h->type); phdr.dp = htons(p->icmpv4h->code); } else { --- 314,320 ---- } break; case IPPROTO_ICMP: ! if (p->icmpv4h) { phdr.sp = htons(p->icmpv4h->type); phdr.dp = htons(p->icmpv4h->code); } else { *************** *** 351,409 **** phdr.classification_id = htonl(pa->class); phdr.priority_id = htonl(pa->prio); ! memcpy(write_buffer+sizeof(Unified2AlertFileHeader),&phdr,sizeof(AlertIPv6Unified2)); ! SCMutexLock(&aun->file_ctx->fp_mutex); ! if ((aun->file_ctx->size_current +(sizeof(hdr) + sizeof(phdr))) > aun->file_ctx->size_limit) { ! if (Unified2AlertRotateFile(t,aun) < 0) { ! SCMutexUnlock(&aun->file_ctx->fp_mutex); ! aun->file_ctx->alerts += i; return -1; } } ! ret = fwrite(write_buffer,len, 1, aun->file_ctx->fp); ! ! if (ret != 1) { ! SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno)); ! SCMutexUnlock(&aun->file_ctx->fp_mutex); ! aun->file_ctx->alerts += i; return -1; } ! fflush(aun->file_ctx->fp); ! aun->file_ctx->size_current += len; ! aun->file_ctx->alerts++; Unified2PacketTypeAlert(t, p, data); ! SCMutexUnlock(&aun->file_ctx->fp_mutex); } - return 0; } /** ! * \brief Function to fill unified2 ipv4 ids type format into the file. * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param p Packet struct used to decide for ipv4 or ipv6 ! * \param data Unified2 thread data. ! * \param pq Packet queue ! * \retval 0 on succces ! * \retval -1 on failure */ ! ! int Unified2IPv4TypeAlert (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { Unified2AlertThread *aun = (Unified2AlertThread *)data; AlertIPv4Unified2 phdr; Unified2AlertFileHeader hdr; PacketAlert *pa; uint8_t ethh_offset = 0; ! int ret, len; char write_buffer[sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv4Unified2)]; if (p->alerts.cnt == 0) --- 345,399 ---- phdr.classification_id = htonl(pa->class); phdr.priority_id = htonl(pa->prio); ! memcpy(write_buffer + sizeof(Unified2AlertFileHeader), &phdr, sizeof(AlertIPv6Unified2)); ! SCMutexLock(&aun->l_ctx->file.fp_mutex); ! if ((aun->l_ctx->file.size_current + (sizeof(hdr) + sizeof(phdr))) > aun->l_ctx->file.size_limit) { ! if (Unified2AlertRotateFile(t, aun) < 0) { ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); ! aun->l_ctx->alerts += i; return -1; } } ! if (fwrite(write_buffer,len, 1, aun->l_ctx->file.fp) != 1) { ! SCLogError(SC_ERR_FWRITE, "write failed: %s", strerror(errno)); ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); ! aun->l_ctx->alerts += i; return -1; } ! fflush(aun->l_ctx->file.fp); ! aun->l_ctx->file.size_current += len; ! aun->l_ctx->alerts++; Unified2PacketTypeAlert(t, p, data); ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); } return 0; } /** ! * \brief Function to fill unified2 ipv4 ids type format into the file. * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param p Packet struct used to decide for ipv4 or ipv6 ! * \param data Unified2 thread data. ! * \param pq Packet queue ! * \retval 0 on succces ! * \retval -1 on failure */ ! int Unified2IPv4TypeAlert(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { Unified2AlertThread *aun = (Unified2AlertThread *)data; AlertIPv4Unified2 phdr; Unified2AlertFileHeader hdr; PacketAlert *pa; uint8_t ethh_offset = 0; ! int len; char write_buffer[sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv4Unified2)]; if (p->alerts.cnt == 0) *************** *** 411,433 **** len = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv4Unified2)); ! memset(write_buffer,0,sizeof(write_buffer)); memset(&hdr, 0, sizeof(Unified2AlertFileHeader)); memset(&phdr, 0, sizeof(AlertIPv4Unified2)); hdr.type = htonl(UNIFIED2_IDS_EVENT_TYPE); hdr.length = htonl(sizeof(AlertIPv4Unified2)); ! memcpy(write_buffer,&hdr,sizeof(Unified2AlertFileHeader)); /* if we have no ethernet header (e.g. when using nfq), we have to create * one ourselves. */ ! if (p->ethh == NULL) { ethh_offset = sizeof(EthernetHdr); } /* fill the hdr structure with the packet data */ - phdr.sensor_id = 0; phdr.event_id = 0; phdr.event_second = htonl(p->ts.tv_sec); --- 401,422 ---- len = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv4Unified2)); ! memset(write_buffer, 0, sizeof(write_buffer)); memset(&hdr, 0, sizeof(Unified2AlertFileHeader)); memset(&phdr, 0, sizeof(AlertIPv4Unified2)); hdr.type = htonl(UNIFIED2_IDS_EVENT_TYPE); hdr.length = htonl(sizeof(AlertIPv4Unified2)); ! memcpy(write_buffer, &hdr, sizeof(Unified2AlertFileHeader)); /* if we have no ethernet header (e.g. when using nfq), we have to create * one ourselves. */ ! if (!p->ethh) { ethh_offset = sizeof(EthernetHdr); } /* fill the hdr structure with the packet data */ phdr.sensor_id = 0; phdr.event_id = 0; phdr.event_second = htonl(p->ts.tv_sec); *************** *** 437,450 **** phdr.protocol = IPV4_GET_RAW_IPPROTO(p->ip4h); ! if(p->action & ACTION_DROP) phdr.packet_action = UNIFIED2_BLOCKED_FLAG; else phdr.packet_action = 0; ! switch(phdr.protocol) { case IPPROTO_ICMP: ! if(p->icmpv4h) { phdr.sp = htons(p->icmpv4h->type); phdr.dp = htons(p->icmpv4h->code); } --- 426,439 ---- phdr.protocol = IPV4_GET_RAW_IPPROTO(p->ip4h); ! if (p->action & ACTION_DROP) phdr.packet_action = UNIFIED2_BLOCKED_FLAG; else phdr.packet_action = 0; ! switch (phdr.protocol) { case IPPROTO_ICMP: ! if (p->icmpv4h) { phdr.sp = htons(p->icmpv4h->type); phdr.dp = htons(p->icmpv4h->code); } *************** *** 471,641 **** phdr.classification_id = htonl(pa->class); phdr.priority_id = htonl(pa->prio); ! memcpy(write_buffer+sizeof(Unified2AlertFileHeader),&phdr,sizeof(AlertIPv4Unified2)); /* check and enforce the filesize limit */ ! SCMutexLock(&aun->file_ctx->fp_mutex); ! if ((aun->file_ctx->size_current +(sizeof(hdr) + sizeof(phdr))) > aun->file_ctx->size_limit) { ! if (Unified2AlertRotateFile(tv,aun) < 0) { ! SCMutexUnlock(&aun->file_ctx->fp_mutex); ! aun->file_ctx->alerts += i; return -1; } } ! ret = fwrite(write_buffer,len, 1, aun->file_ctx->fp); ! if (ret != 1) { ! SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno)); ! SCMutexUnlock(&aun->file_ctx->fp_mutex); ! aun->file_ctx->alerts += i; return -1; } ! fflush(aun->file_ctx->fp); ! aun->file_ctx->size_current += len; /* Write the alert (it doesn't lock inside, since we * already locked here for rotation check) */ Unified2PacketTypeAlert(tv, p, data); ! SCMutexUnlock(&aun->file_ctx->fp_mutex); } ! aun->file_ctx->alerts += p->alerts.cnt; return 0; } /** ! * \brief Thread init function. * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param initdata Unified2 thread initial data. ! * \param data Unified2 thread data. ! * \retval TM_ECODE_OK on succces ! * \retval TM_ECODE_FAILED on failure */ - TmEcode Unified2AlertThreadInit(ThreadVars *t, void *initdata, void **data) { Unified2AlertThread *aun = malloc(sizeof(Unified2AlertThread)); ! if (aun == NULL) { return TM_ECODE_FAILED; - } memset(aun, 0, sizeof(Unified2AlertThread)); ! if(initdata == NULL) ! { ! SCLogDebug("Error getting context for Unified2Alert. \"initdata\" argument NULL"); free(aun); return TM_ECODE_FAILED; } /** Use the Ouptut Context (file pointer and mutex) */ ! aun->file_ctx = (LogFileCtx*) initdata; *data = (void *)aun; return TM_ECODE_OK; } /** ! * \brief Thread deinit function. * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param data Unified2 thread data. ! * \retval TM_ECODE_OK on succces ! * \retval TM_ECODE_FAILED on failure */ - TmEcode Unified2AlertThreadDeinit(ThreadVars *t, void *data) { Unified2AlertThread *aun = (Unified2AlertThread *)data; ! if (aun == NULL) { ! goto error; ! } ! if (!(aun->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) { ! SCLogInfo("Alert unified 2 module wrote %"PRIu64" alerts", aun->file_ctx->alerts); /* Do not print it for each thread */ ! aun->file_ctx->flags |= LOGFILE_ALERTS_PRINTED; } /* clear memory */ memset(aun, 0, sizeof(Unified2AlertThread)); free(aun); return TM_ECODE_OK; - - error: - return TM_ECODE_FAILED; } ! /** \brief Create a new LogFileCtx from the provided ConfNode. ! * \param conf The configuration node for this output. ! * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ ! LogFileCtx *Unified2AlertInitCtx(ConfNode *conf) { ! int ret=0; ! LogFileCtx* file_ctx=LogFileNewCtx(); ! ! if (file_ctx == NULL) { ! SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Unified2AlertInitCtx: " ! "Couldn't create new file_ctx"); return NULL; } ! const char *filename = NULL; ! if (conf != NULL) { /* To faciliate unit tests. */ ! filename = ConfNodeLookupChildValue(conf, "filename"); ! } ! if (filename == NULL) filename = DEFAULT_LOG_FILENAME; ! file_ctx->prefix = strdup(filename); - const char *s_limit = NULL; uint32_t limit = DEFAULT_LIMIT; ! if (conf != NULL) { ! s_limit = ConfNodeLookupChildValue(conf, "limit"); ! if (s_limit != NULL) { ! if (ByteExtractStringUint32(&limit, 10, 0, s_limit) == -1) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, ! "Fail to initialize unified2 output, invalid limit: %s", ! s_limit); ! exit(EXIT_FAILURE); ! } ! if (limit < MIN_LIMIT) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, ! "Fail to initialize unified2 output, limit less than " ! "allowed minimum."); ! exit(EXIT_FAILURE); ! } } } ! file_ctx->size_limit = limit * 1024 * 1024; ! ret = Unified2AlertOpenFileCtx(file_ctx, filename); ! if (ret < 0) return NULL; ! SCLogInfo("Unified2-alert initialized: filename %s, limit %"PRIu32" MB", ! filename, limit); ! return file_ctx; } ! /** \brief Read the config set the file pointer, open the file ! * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() ! * \param prefix Prefix of the log file. ! * \return -1 if failure, 0 if succesful ! * */ ! int Unified2AlertOpenFileCtx(LogFileCtx *file_ctx, const char *prefix) { ! int ret = 0; ! char *filename = NULL; ! if (file_ctx->filename != NULL) ! filename = file_ctx->filename; else ! filename = file_ctx->filename = malloc(PATH_MAX); /* XXX some sane default? */ /** get the time so we can have a filename with seconds since epoch */ struct timeval ts; --- 460,610 ---- phdr.classification_id = htonl(pa->class); phdr.priority_id = htonl(pa->prio); ! memcpy(write_buffer + sizeof(Unified2AlertFileHeader), &phdr, sizeof(AlertIPv4Unified2)); /* check and enforce the filesize limit */ ! SCMutexLock(&aun->l_ctx->file.fp_mutex); ! if ((aun->l_ctx->file.size_current + (sizeof(hdr) + sizeof(phdr))) > aun->l_ctx->file.size_limit) { ! if (Unified2AlertRotateFile(tv, aun) < 0) { ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); ! aun->l_ctx->alerts += i; return -1; } } ! if (fwrite(write_buffer,len, 1, aun->l_ctx->file.fp) != 1) { ! SCLogError(SC_ERR_FWRITE, "write failed: %s", strerror(errno)); ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); ! aun->l_ctx->alerts += i; return -1; } ! fflush(aun->l_ctx->file.fp); ! aun->l_ctx->file.size_current += len; /* Write the alert (it doesn't lock inside, since we * already locked here for rotation check) */ Unified2PacketTypeAlert(tv, p, data); ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); } ! aun->l_ctx->alerts += p->alerts.cnt; return 0; } /** ! * \brief Thread init function. * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param initdata Unified2 thread initial data. ! * \param data Unified2 thread data. ! * \retval TM_ECODE_OK on succces ! * \retval TM_ECODE_FAILED on failure */ TmEcode Unified2AlertThreadInit(ThreadVars *t, void *initdata, void **data) { Unified2AlertThread *aun = malloc(sizeof(Unified2AlertThread)); ! if (!aun) return TM_ECODE_FAILED; memset(aun, 0, sizeof(Unified2AlertThread)); ! ! if (!initdata) { ! SCLogDebug("Error getting context for Unified2Alert. \"initdata\" argument is NULL"); free(aun); return TM_ECODE_FAILED; } + /** Use the Ouptut Context (file pointer and mutex) */ ! aun->l_ctx = (LogCtx*)initdata; *data = (void *)aun; return TM_ECODE_OK; } /** ! * \brief Thread deinit function. * ! * \param t Thread Variable containing input/output queue, cpu affinity etc. ! * \param data Unified2 thread data. ! * \retval TM_ECODE_OK on succces ! * \retval TM_ECODE_FAILED on failure */ TmEcode Unified2AlertThreadDeinit(ThreadVars *t, void *data) { Unified2AlertThread *aun = (Unified2AlertThread *)data; ! if (!aun) ! return TM_ECODE_FAILED; ! if (!(aun->l_ctx->file.flags & LOGFILE_ALERTS_PRINTED)) { ! SCLogInfo("Alert unified2 module wrote %" PRIu64 " alerts", aun->l_ctx->alerts); /* Do not print it for each thread */ ! aun->l_ctx->file.flags |= LOGFILE_ALERTS_PRINTED; } /* clear memory */ memset(aun, 0, sizeof(Unified2AlertThread)); free(aun); return TM_ECODE_OK; } ! /** ! * \brief Create a new LogCtx from the provided ConfNode. ! * \param conf The configuration node for this output. ! * \return NULL if failure, LogCtx pointer to the l_ctx if succesful * */ ! LogCtx *Unified2AlertInitCtx(ConfNode *conf) { ! LogCtx *l_ctx = LogNewCtx(); ! if (!l_ctx) { ! SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Could not create new output context"); return NULL; } ! const char *filename = ConfNodeLookupChildValue(conf, "filename"); ! if (!filename) filename = DEFAULT_LOG_FILENAME; ! l_ctx->file.prefix = strdup(filename); uint32_t limit = DEFAULT_LIMIT; ! const char *s_limit = NULL; ! s_limit = ConfNodeLookupChildValue(conf, "limit"); ! if (!s_limit) { ! if (ByteExtractStringUint32(&limit, 10, 0, s_limit) == -1) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, "Fail to initialize unified2 output, invalid limit: %s", s_limit); ! exit(EXIT_FAILURE); ! } ! if (limit < MIN_LIMIT) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, "Fail to initialize unified2 output, limit less than allowed minimum"); ! exit(EXIT_FAILURE); } } ! l_ctx->file.size_limit = limit * 1024 * 1024; ! if (Unified2AlertOpenFileCtx(l_ctx, filename) < 0) return NULL; ! SCLogInfo("Unified2-alert initialized: filename %s, limit %" PRIu32 " MB", filename, limit); ! return l_ctx; } ! /** ! * \brief Read the config set the file pointer, open the file ! * \param l_ctx pointer to a created LogCtx using LogNewCtx() ! * \param prefix Prefix of the log file. ! * \return -1 if failure, 0 if succesful ! */ ! int Unified2AlertOpenFileCtx(LogCtx *l_ctx, const char *prefix) { ! char *filename; ! if (l_ctx->file.filename) ! filename = l_ctx->file.filename; else ! filename = l_ctx->file.filename = malloc(PATH_MAX); /* XXX some sane default? */ /** get the time so we can have a filename with seconds since epoch */ struct timeval ts; *************** *** 655,686 **** snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, prefix, (uint32_t)ts.tv_sec); /* XXX filename & location */ ! file_ctx->fp = fopen(filename, "wb"); ! if (file_ctx->fp == NULL) { ! SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", filename, ! strerror(errno)); ! ret = -1; } ! return ret; } #ifdef UNITTESTS - /** ! * \test Test the ethernet+ipv4+tcp unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! ! static int Unified2Test01 (void) { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogFileCtx *lf; uint8_t raw_ipv4_tcp[] = { 0x00, 0x14, 0xbf, 0xe8, 0xcb, 0x26, 0xaa, 0x00, --- 624,653 ---- snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, prefix, (uint32_t)ts.tv_sec); /* XXX filename & location */ ! l_ctx->file.fp = fopen(filename, "wb"); ! if (!l_ctx->file.fp) { ! SCLogError(SC_ERR_FOPEN, "Failed to open %s: %s", filename, strerror(errno)); ! return -1; } ! return 0; } #ifdef UNITTESTS /** ! * \test Test the ethernet+ipv4+tcp unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! static int Unified2Test01(void) ! { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogCtx *l_ctx; uint8_t raw_ipv4_tcp[] = { 0x00, 0x14, 0xbf, 0xe8, 0xcb, 0x26, 0xaa, 0x00, *************** *** 694,700 **** 0x28, 0x81, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x06}; Packet p; - int ret; memset(&dtv, 0, sizeof(DecodeThreadVars)); memset(&tv, 0, sizeof(ThreadVars)); --- 661,666 ---- *************** *** 713,749 **** FlowShutdown(); ! lf=Unified2AlertInitCtx(NULL); ! if(lf == NULL) return 0; ! ret = Unified2AlertThreadInit(&tv, lf, &data); ! if(ret == TM_ECODE_FAILED) return 0; ! ret = Unified2Alert(&tv, &p, data, &pq); ! if(ret == TM_ECODE_FAILED) return 0; ! ret = Unified2AlertThreadDeinit(&tv, data); ! if(ret == -1) return 0; ! if(LogFileFreeCtx(lf)==0) return 0; return 1; } /** ! * \test Test the ethernet+ipv6+tcp unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! ! static int Unified2Test02 (void) { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogFileCtx *lf; uint8_t raw_ipv6_tcp[] = { 0x00, 0x11, 0x25, 0x82, 0x95, 0xb5, 0x00, 0xd0, --- 679,716 ---- FlowShutdown(); ! l_ctx = Unified2AlertInitCtx(NULL); ! if (!l_ctx) return 0; ! ! if (Unified2AlertThreadInit(&tv, lf, &data) == TM_ECODE_FAILED) return 0; ! ! if (Unified2Alert(&tv, &p, data, &pq) == TM_ECODE_FAILED) return 0; ! ! if (Unified2AlertThreadDeinit(&tv, data) == -1) return 0; ! if (LogFreeCtx(l_ctx) == 0) return 0; + return 1; } /** ! * \test Test the ethernet+ipv6+tcp unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! static int Unified2Test02(void) ! { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogCtx *l_ctx; uint8_t raw_ipv6_tcp[] = { 0x00, 0x11, 0x25, 0x82, 0x95, 0xb5, 0x00, 0xd0, *************** *** 759,765 **** 0x08, 0x0a, 0x00, 0x0a, 0x22, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x05 }; Packet p; - int ret; memset(&dtv, 0, sizeof(DecodeThreadVars)); memset(&tv, 0, sizeof(ThreadVars)); --- 726,731 ---- *************** *** 778,816 **** FlowShutdown(); ! lf=Unified2AlertInitCtx(NULL); ! if(lf == NULL) return 0; ! ret = Unified2AlertThreadInit(&tv, lf, &data); ! if(ret == -1) return 0; ! ret = Unified2Alert(&tv, &p, data, &pq); ! if(ret == TM_ECODE_FAILED) return 0; ! ret = Unified2AlertThreadDeinit(&tv, data); ! if(ret == -1) return 0; ! if(LogFileFreeCtx(lf)==0) return 0; return 1; } - /** ! * \test Test the GRE unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! ! static int Unified2Test03 (void) { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogFileCtx *lf; uint8_t raw_gre[] = { 0x00, 0x0e, 0x50, 0x06, 0x42, 0x96, 0xaa, 0x00, --- 744,781 ---- FlowShutdown(); ! l_ctx = Unified2AlertInitCtx(NULL); ! if (!l_ctx) return 0; ! ! if (Unified2AlertThreadInit(&tv, lf, &data) == -1) return 0; ! ! if (Unified2Alert(&tv, &p, data, &pq) == TM_ECODE_FAILED) return 0; ! ! if (Unified2AlertThreadDeinit(&tv, data) == -1) return 0; ! if (LogFreeCtx(l_ctx) == 0) return 0; return 1; } /** ! * \test Test the GRE unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! static int Unified2Test03(void) ! { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogCtx *l_ctx; uint8_t raw_gre[] = { 0x00, 0x0e, 0x50, 0x06, 0x42, 0x96, 0xaa, 0x00, *************** *** 831,837 **** 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x0d, 0x0a}; Packet p; - int ret; memset(&dtv, 0, sizeof(DecodeThreadVars)); memset(&tv, 0, sizeof(ThreadVars)); --- 796,801 ---- *************** *** 850,887 **** FlowShutdown(); ! lf=Unified2AlertInitCtx(NULL); ! if(lf == NULL) return 0; ! ret = Unified2AlertThreadInit(&tv, lf, &data); ! if(ret == -1) return 0; ! ret = Unified2Alert(&tv, &p, data, &pq); ! if(ret == TM_ECODE_FAILED) return 0; ! ret = Unified2AlertThreadDeinit(&tv, data); ! if(ret == -1) return 0; ! if(LogFileFreeCtx(lf)==0) return 0; return 1; } /** ! * \test Test the PPP unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! ! static int Unified2Test04 (void) { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogFileCtx *lf; uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00, 0x2c, --- 814,851 ---- FlowShutdown(); ! l_ctx = Unified2AlertInitCtx(NULL); ! if (!l_ctx) return 0; ! ! if (Unified2AlertThreadInit(&tv, lf, &data) == -1) return 0; ! ! if (Unified2Alert(&tv, &p, data, &pq) == TM_ECODE_FAILED) return 0; ! ! if (Unified2AlertThreadDeinit(&tv, data) == -1) return 0; ! if (LogFreeCtx(l_ctx) == 0) return 0; return 1; } /** ! * \test Test the PPP unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! static int Unified2Test04(void) ! { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogCtx *l_ctx; uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00, 0x2c, *************** *** 891,897 **** 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x10, 0x20, 0xdd, 0xe1, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4}; Packet p; - int ret; memset(&dtv, 0, sizeof(DecodeThreadVars)); memset(&tv, 0, sizeof(ThreadVars)); --- 855,860 ---- *************** *** 910,947 **** FlowShutdown(); ! lf=Unified2AlertInitCtx(NULL); ! if(lf == NULL) return 0; ! ret = Unified2AlertThreadInit(&tv, lf, &data); ! if(ret == -1) return 0; ! ret = Unified2Alert(&tv, &p, data, &pq); ! if(ret == TM_ECODE_FAILED) return 0; ! ret = Unified2AlertThreadDeinit(&tv, data); ! if(ret == -1) return 0; ! if(LogFileFreeCtx(lf)==0) return 0; return 1; } /** ! * \test Test the ethernet+ipv4+tcp droped unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! ! static int Unified2Test05 (void) { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogFileCtx *lf; uint8_t raw_ipv4_tcp[] = { 0x00, 0x14, 0xbf, 0xe8, 0xcb, 0x26, 0xaa, 0x00, --- 873,910 ---- FlowShutdown(); ! l_ctx = Unified2AlertInitCtx(NULL); ! if (!l_ctx) return 0; ! ! if (Unified2AlertThreadInit(&tv, lf, &data) == -1) return 0; ! ! if (Unified2Alert(&tv, &p, data, &pq) == TM_ECODE_FAILED) return 0; ! ! if (Unified2AlertThreadDeinit(&tv, data) == -1) return 0; ! if (LogFreeCtx(l_ctx) == 0) return 0; return 1; } /** ! * \test Test the Ethernet + IPv4 + TCP droped unified2 test * ! * \retval 1 on succces ! * \retval 0 on failure */ ! static int Unified2Test05(void) ! { ThreadVars tv; DecodeThreadVars dtv; PacketQueue pq; void *data = NULL; ! LogCtx *l_ctx; uint8_t raw_ipv4_tcp[] = { 0x00, 0x14, 0xbf, 0xe8, 0xcb, 0x26, 0xaa, 0x00, *************** *** 955,961 **** 0x28, 0x81, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x06}; Packet p; - int ret; memset(&dtv, 0, sizeof(DecodeThreadVars)); memset(&tv, 0, sizeof(ThreadVars)); --- 918,923 ---- *************** *** 976,995 **** p.action = ACTION_DROP; ! lf=Unified2AlertInitCtx(NULL); ! if(lf == NULL) return 0; ! ret = Unified2AlertThreadInit(&tv, lf, &data); ! if(ret == -1) return 0; ! ret = Unified2Alert(&tv, &p, data, &pq); ! if(ret == TM_ECODE_FAILED) return 0; ! ret = Unified2AlertThreadDeinit(&tv, data); ! if(ret == TM_ECODE_FAILED) return 0; ! if(LogFileFreeCtx(lf)==0) return 0; return 1; --- 938,957 ---- p.action = ACTION_DROP; ! l_ctx = Unified2AlertInitCtx(NULL); ! if (!l_ctx) return 0; ! ! if (Unified2AlertThreadInit(&tv, lf, &data) == -1) return 0; ! ! if (Unified2Alert(&tv, &p, data, &pq) == TM_ECODE_FAILED) return 0; ! ! if (Unified2AlertThreadDeinit(&tv, data) == TM_ECODE_FAILED) return 0; ! if (LogFreeCtx(l_ctx) == 0) return 0; return 1; *************** *** 1003,1039 **** */ static int Unified2TestRotate01(void) { - int ret = 0; int r = 0; ThreadVars tv; ! LogFileCtx *lf; void *data = NULL; ! lf = Unified2AlertInitCtx(NULL); ! if (lf == NULL) return 0; ! char *filename = strdup(lf->filename); memset(&tv, 0, sizeof(ThreadVars)); ! if (lf == NULL) return 0; ! ret = Unified2AlertThreadInit(&tv, lf, &data); ! if (ret == TM_ECODE_FAILED) { ! LogFileFreeCtx(lf); return 0; } TimeSetIncrementTime(1); ! ret = Unified2AlertRotateFile(&tv, data); ! if (ret == -1) goto error; ! if (strcmp(filename, lf->filename) == 0) { ! SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, ! "filename \"%s\" == \"%s\": ", filename, lf->filename); goto error; } --- 965,998 ---- */ static int Unified2TestRotate01(void) { int r = 0; ThreadVars tv; ! LogCtx *l_ctx; void *data = NULL; ! l_ctx = Unified2AlertInitCtx(NULL); ! if (!l_ctx) return 0; ! ! char *filename = strdup(l_ctx->file.filename); memset(&tv, 0, sizeof(ThreadVars)); ! if (!l_ctx) return 0; ! if (Unified2AlertThreadInit(&tv, lf, &data) == TM_ECODE_FAILED) { ! LogFreeCtx(l_ctx); return 0; } TimeSetIncrementTime(1); ! if (Unified2AlertRotateFile(&tv, data) == -1) goto error; ! if (strcmp(filename, l_ctx->file.filename) == 0) { ! SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Filename \"%s\" is equal \"%s\"", filename, lf->filename); goto error; } *************** *** 1041,1048 **** error: Unified2AlertThreadDeinit(&tv, data); ! if (lf != NULL) LogFileFreeCtx(lf); ! if (filename != NULL) free(filename); return r; } #endif --- 1000,1009 ---- error: Unified2AlertThreadDeinit(&tv, data); ! if (l_ctx) ! LogFreeCtx(lf); ! if (filename) ! free(filename); return r; } #endif *************** *** 1050,1056 **** /** * \brief this function registers unit tests for Unified2 */ ! void Unified2RegisterTests (void) { #ifdef UNITTESTS UtRegisterTest("Unified2Test01 -- Ipv4 test", Unified2Test01, 1); UtRegisterTest("Unified2Test02 -- Ipv6 test", Unified2Test02, 1); --- 1011,1018 ---- /** * \brief this function registers unit tests for Unified2 */ ! void Unified2RegisterTests(void) ! { #ifdef UNITTESTS UtRegisterTest("Unified2Test01 -- Ipv4 test", Unified2Test01, 1); UtRegisterTest("Unified2Test02 -- Ipv6 test", Unified2Test02, 1); diff -crN 1/src/alert-unified2-alert.h 2/src/alert-unified2-alert.h *** 1/src/alert-unified2-alert.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-unified2-alert.h 2010-03-11 14:45:50.577225799 +0300 *************** *** 1,6 **** ! /** Copyright (c) 2009 Open Information Security Foundation ! * ! * \author Breno Silva */ #ifndef __ALERT_UNIFIED2_ALERT_H__ --- 1,9 ---- ! /* Copyright (c) 2010 Andrew A. Usenok */ ! /* Copyright (c) 2009 Open Information Security Foundation */ ! ! /** ! * \file ! * \author Breno Silva */ #ifndef __ALERT_UNIFIED2_ALERT_H__ *************** *** 22,28 **** #define UNIFIED2_IDS_EVENT_IPV6_MPLS_TYPE 100 void TmModuleUnified2AlertRegister (void); ! LogFileCtx *Unified2AlertInitCtx(ConfNode *); #endif /* __ALERT_UNIFIED2_ALERT_H__ */ - --- 25,30 ---- #define UNIFIED2_IDS_EVENT_IPV6_MPLS_TYPE 100 void TmModuleUnified2AlertRegister (void); ! LogCtx *Unified2AlertInitCtx(ConfNode *); #endif /* __ALERT_UNIFIED2_ALERT_H__ */ diff -crN 1/src/alert-unified-alert.c 2/src/alert-unified-alert.c *** 1/src/alert-unified-alert.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-unified-alert.c 2010-03-11 14:45:50.863210992 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ /* alert unified *************** *** 50,56 **** TmEcode AlertUnifiedAlert (ThreadVars *, Packet *, void *, PacketQueue *); TmEcode AlertUnifiedAlertThreadInit(ThreadVars *, void *, void **); TmEcode AlertUnifiedAlertThreadDeinit(ThreadVars *, void *); ! int AlertUnifiedAlertOpenFileCtx(LogFileCtx *, const char *); void AlertUnifiedAlertRegisterTests (void); void TmModuleAlertUnifiedAlertRegister (void) { --- 51,57 ---- TmEcode AlertUnifiedAlert (ThreadVars *, Packet *, void *, PacketQueue *); TmEcode AlertUnifiedAlertThreadInit(ThreadVars *, void *, void **); TmEcode AlertUnifiedAlertThreadDeinit(ThreadVars *, void *); ! int AlertUnifiedAlertOpenFileCtx(LogCtx *, const char *); void AlertUnifiedAlertRegisterTests (void); void TmModuleAlertUnifiedAlertRegister (void) { *************** *** 64,71 **** } typedef struct AlertUnifiedAlertThread_ { ! /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ ! LogFileCtx* file_ctx; } AlertUnifiedAlertThread; #define ALERTUNIFIEDALERT_ALERTMAGIC 0xDEAD4137 /* taken from Snort */ --- 65,72 ---- } typedef struct AlertUnifiedAlertThread_ { ! /** LogCtx has the pointer to the file and a mutex to allow multithreading */ ! LogCtx* l_ctx; } AlertUnifiedAlertThread; #define ALERTUNIFIEDALERT_ALERTMAGIC 0xDEAD4137 /* taken from Snort */ *************** *** 110,118 **** uint32_t flags; } AlertUnifiedAlertPacketHeader; ! int AlertUnifiedAlertWriteFileHeader(LogFileCtx *file_ctx) { int ret; ! if (file_ctx->flags & LOGFILE_HEADER_WRITTEN) return 0; /** write the fileheader to the file so the reader can recognize it */ --- 111,119 ---- uint32_t flags; } AlertUnifiedAlertPacketHeader; ! int AlertUnifiedAlertWriteFileHeader(LogCtx *l_ctx) { int ret; ! if (l_ctx->file.flags & LOGFILE_HEADER_WRITTEN) return 0; /** write the fileheader to the file so the reader can recognize it */ *************** *** 122,165 **** hdr.ver_minor = ALERTUNIFIEDALERT_VERMINOR; hdr.timezone = 0; /* XXX */ ! ret = fwrite(&hdr, sizeof(AlertUnifiedAlertFileHeader), 1, file_ctx->fp); if (ret != 1) { ! SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: ret = %" PRId32 ", %s", ! ret, strerror(errno)); return -1; } ! fflush(file_ctx->fp); ! file_ctx->size_current = sizeof(hdr); - file_ctx->flags |= LOGFILE_HEADER_WRITTEN; return 0; } int AlertUnifiedAlertCloseFile(ThreadVars *t, AlertUnifiedAlertThread *aun) { ! if (aun->file_ctx->fp != NULL) { ! fclose(aun->file_ctx->fp); } ! aun->file_ctx->size_current = 0; ! aun->file_ctx->flags = 0; return 0; } int AlertUnifiedAlertRotateFile(ThreadVars *t, AlertUnifiedAlertThread *aun) { if (AlertUnifiedAlertCloseFile(t,aun) < 0) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, ! "Error: AlertUnifiedAlertCloseFile failed"); return -1; } ! if (AlertUnifiedAlertOpenFileCtx(aun->file_ctx,aun->file_ctx->prefix) < 0) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, ! "Error: AlertUnifiedLogOpenFileCtx, open new log file failed"); return -1; } ! if (AlertUnifiedAlertWriteFileHeader(aun->file_ctx) < 0) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, "Error: " ! "AlertUnifiedLogAppendFile, write unified header failed"); return -1; } --- 123,162 ---- hdr.ver_minor = ALERTUNIFIEDALERT_VERMINOR; hdr.timezone = 0; /* XXX */ ! ret = fwrite(&hdr, sizeof(AlertUnifiedAlertFileHeader), 1, l_ctx->file.fp); if (ret != 1) { ! SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: ret = %" PRId32 ", %s", ret, strerror(errno)); return -1; } ! fflush(l_ctx->file.fp); ! l_ctx->file.size_current = sizeof(hdr); ! l_ctx->file.flags |= LOGFILE_HEADER_WRITTEN; return 0; } int AlertUnifiedAlertCloseFile(ThreadVars *t, AlertUnifiedAlertThread *aun) { ! if (aun->l_ctx->file.fp) { ! fclose(aun->l_ctx->file.fp); } ! aun->l_ctx->file.size_current = 0; ! aun->l_ctx->file.flags = 0; return 0; } int AlertUnifiedAlertRotateFile(ThreadVars *t, AlertUnifiedAlertThread *aun) { if (AlertUnifiedAlertCloseFile(t,aun) < 0) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, "Error: AlertUnifiedAlertCloseFile failed"); return -1; } ! if (AlertUnifiedAlertOpenFileCtx(aun->l_ctx, aun->l_ctx->file.prefix) < 0) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, "Error: AlertUnifiedLogOpenFileCtx, open new log file failed"); return -1; } ! if (AlertUnifiedAlertWriteFileHeader(aun->l_ctx) < 0) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, "Error: AlertUnifiedLogAppendFile, write unified header failed"); return -1; } *************** *** 207,236 **** hdr.sig_class = pa->class; hdr.sig_prio = pa->prio; ! SCMutexLock(&aun->file_ctx->fp_mutex); /** check and enforce the filesize limit, thread safe */ ! if ((aun->file_ctx->size_current + sizeof(hdr)) > aun->file_ctx->size_limit) { if (AlertUnifiedAlertRotateFile(tv,aun) < 0) { ! SCMutexUnlock(&aun->file_ctx->fp_mutex); ! aun->file_ctx->alerts += i; return TM_ECODE_FAILED; } } /* Then the unified header */ ! ret = fwrite(&hdr, sizeof(AlertUnifiedAlertPacketHeader), 1, aun->file_ctx->fp); if (ret != 1) { SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno)); ! SCMutexUnlock(&aun->file_ctx->fp_mutex); ! aun->file_ctx->alerts += i; return TM_ECODE_FAILED; } /* force writing to disk so barnyard will not read half * written records and choke. */ ! fflush(aun->file_ctx->fp); ! aun->file_ctx->size_current += sizeof(hdr); ! aun->file_ctx->alerts++; ! SCMutexUnlock(&aun->file_ctx->fp_mutex); } return TM_ECODE_OK; --- 204,233 ---- hdr.sig_class = pa->class; hdr.sig_prio = pa->prio; ! SCMutexLock(&aun->l_ctx->file.fp_mutex); /** check and enforce the filesize limit, thread safe */ ! if ((aun->l_ctx->file.size_current + sizeof(hdr)) > aun->l_ctx->file.size_limit) { if (AlertUnifiedAlertRotateFile(tv,aun) < 0) { ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); ! aun->l_ctx->alerts += i; return TM_ECODE_FAILED; } } /* Then the unified header */ ! ret = fwrite(&hdr, sizeof(AlertUnifiedAlertPacketHeader), 1, aun->l_ctx->file.fp); if (ret != 1) { SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno)); ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); ! aun->l_ctx->alerts += i; return TM_ECODE_FAILED; } /* force writing to disk so barnyard will not read half * written records and choke. */ ! fflush(aun->l_ctx->file.fp); ! aun->l_ctx->file.size_current += sizeof(hdr); ! aun->l_ctx->alerts++; ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); } return TM_ECODE_OK; *************** *** 239,256 **** TmEcode AlertUnifiedAlertThreadInit(ThreadVars *t, void *initdata, void **data) { AlertUnifiedAlertThread *aun = malloc(sizeof(AlertUnifiedAlertThread)); ! if (aun == NULL) { return TM_ECODE_FAILED; } memset(aun, 0, sizeof(AlertUnifiedAlertThread)); ! if (initdata == NULL) { ! SCLogDebug("Error getting context for UnifiedAlert. \"initdata\" argument NULL"); free(aun); return TM_ECODE_FAILED; } /** Use the Ouptut Context (file pointer and mutex) */ ! aun->file_ctx = (LogFileCtx*) initdata; *data = (void *)aun; return TM_ECODE_OK; --- 236,253 ---- TmEcode AlertUnifiedAlertThreadInit(ThreadVars *t, void *initdata, void **data) { AlertUnifiedAlertThread *aun = malloc(sizeof(AlertUnifiedAlertThread)); ! if (!aun) { return TM_ECODE_FAILED; } memset(aun, 0, sizeof(AlertUnifiedAlertThread)); ! if (!initdata) { ! SCLogDebug("Error getting context for UnifiedAlert. \"initdata\" argument NULL"); free(aun); return TM_ECODE_FAILED; } /** Use the Ouptut Context (file pointer and mutex) */ ! aun->l_ctx = (LogCtx*)initdata; *data = (void *)aun; return TM_ECODE_OK; *************** *** 259,353 **** TmEcode AlertUnifiedAlertThreadDeinit(ThreadVars *t, void *data) { AlertUnifiedAlertThread *aun = (AlertUnifiedAlertThread *)data; ! if (aun == NULL) { ! goto error; } ! if (!(aun->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) { ! SCLogInfo("Alert unified 1 alert module wrote %"PRIu64" alerts", aun->file_ctx->alerts); /* Do not print it for each thread */ ! aun->file_ctx->flags |= LOGFILE_ALERTS_PRINTED; } /* clear memory */ memset(aun, 0, sizeof(AlertUnifiedAlertThread)); free(aun); return TM_ECODE_OK; - - error: - return TM_ECODE_FAILED; } ! /** \brief Create a new LogFileCtx for unified alert logging. * \param conf The ConfNode for this output. ! * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ ! LogFileCtx *AlertUnifiedAlertInitCtx(ConfNode *conf) { ! int ret = 0; ! LogFileCtx *file_ctx = LogFileNewCtx(); ! if (file_ctx == NULL) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, ! "AlertUnifiedAlertInitCtx: Couldn't create new file_ctx"); return NULL; } ! const char *filename = NULL; ! if (conf != NULL) ! filename = ConfNodeLookupChildValue(conf, "filename"); if (filename == NULL) filename = DEFAULT_LOG_FILENAME; ! file_ctx->prefix = strdup(filename); - const char *s_limit = NULL; uint32_t limit = DEFAULT_LIMIT; ! if (conf != NULL) { ! s_limit = ConfNodeLookupChildValue(conf, "limit"); ! if (s_limit != NULL) { ! if (ByteExtractStringUint32(&limit, 10, 0, s_limit) == -1) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, ! "Fail to initialize unified alert output, invalid limit: %s", ! s_limit); ! exit(EXIT_FAILURE); ! } ! if (limit < MIN_LIMIT) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, ! "Fail to initialize unified alert output, limit less than " ! "allowed minimum."); ! exit(EXIT_FAILURE); ! } } } ! file_ctx->size_limit = limit * 1024 * 1024; ! ret = AlertUnifiedAlertOpenFileCtx(file_ctx, filename); ! if (ret < 0) return NULL; ! SCLogInfo("Unified-alert initialized: filename %s, limit %"PRIu32" MB", ! filename, limit); ! return file_ctx; } /** \brief Read the config set the file pointer, open the file ! * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() * \param config_file for loading separate configs * \return -1 if failure, 0 if succesful * */ ! int AlertUnifiedAlertOpenFileCtx(LogFileCtx *file_ctx, const char *prefix) { ! int ret = 0; ! char *filename = NULL; ! if (file_ctx->filename != NULL) ! filename = file_ctx->filename; else ! filename = file_ctx->filename = malloc(PATH_MAX); /* XXX some sane default? */ /* get the time so we can have a filename with seconds since epoch */ struct timeval ts; ! memset (&ts, 0, sizeof(struct timeval)); extern int run_mode; if (run_mode == MODE_UNITTEST) --- 256,334 ---- TmEcode AlertUnifiedAlertThreadDeinit(ThreadVars *t, void *data) { AlertUnifiedAlertThread *aun = (AlertUnifiedAlertThread *)data; ! if (!aun) { ! return TM_ECODE_FAILED; } ! if (!(aun->l_ctx->file.flags & LOGFILE_ALERTS_PRINTED)) { ! SCLogInfo("Alert unified 1 alert module wrote %" PRIu64 " alerts", aun->l_ctx->alerts); /* Do not print it for each thread */ ! aun->l_ctx->file.flags |= LOGFILE_ALERTS_PRINTED; } + /* clear memory */ memset(aun, 0, sizeof(AlertUnifiedAlertThread)); free(aun); return TM_ECODE_OK; } ! /** \brief Create a new LogCtx for unified alert logging. * \param conf The ConfNode for this output. ! * \return NULL if failure, LogCtx* to the l_ctx if succesful * */ ! LogCtx *AlertUnifiedAlertInitCtx(ConfNode *conf) { ! LogCtx *l_ctx = LogNewCtx(); ! if (!l_ctx) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, "AlertUnifiedAlertInitCtx: Could not create new output context"); return NULL; } ! const char *filename = ConfNodeLookupChildValue(conf, "filename"); if (filename == NULL) filename = DEFAULT_LOG_FILENAME; ! l_ctx->file.prefix = strdup(filename); uint32_t limit = DEFAULT_LIMIT; ! const char *s_limit = ConfNodeLookupChildValue(conf, "limit"); ! if (s_limit) { ! if (ByteExtractStringUint32(&limit, 10, 0, s_limit) == -1) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, "AlertUnifiedAlertInitCtx: Fail to initialize unified alert output, invalid limit: %s", s_limit); ! exit(EXIT_FAILURE); ! } ! if (limit < MIN_LIMIT) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, "AlertUnifiedAlertInitCtx: Fail to initialize unified alert output, limit less than allowed minimum"); ! exit(EXIT_FAILURE); } } ! l_ctx->file.size_limit = limit * 1024 * 1024; ! if (AlertUnifiedAlertOpenFileCtx(l_ctx, filename) < 0) return NULL; ! SCLogInfo("Unified-alert initialized: filename %s, limit %" PRIu32 " MB", filename, limit); ! return l_ctx; } /** \brief Read the config set the file pointer, open the file ! * \param l_ctx pointer to a created LogCtx using LogCtx() * \param config_file for loading separate configs * \return -1 if failure, 0 if succesful * */ ! int AlertUnifiedAlertOpenFileCtx(LogCtx *l_ctx, const char *prefix) { ! char *filename; ! if (l_ctx->file.filename) ! filename = l_ctx->file.filename; else ! filename = l_ctx->file.filename = malloc(PATH_MAX); /* XXX some sane default? */ /* get the time so we can have a filename with seconds since epoch */ struct timeval ts; ! memset(&ts, 0, sizeof(struct timeval)); extern int run_mode; if (run_mode == MODE_UNITTEST) *************** *** 363,385 **** snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, prefix, (uint32_t)ts.tv_sec); /* XXX filename & location */ ! file_ctx->fp = fopen(filename, "wb"); ! if (file_ctx->fp == NULL) { ! SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", filename, ! strerror(errno)); ! ret = -1; } ! file_ctx->flags = 0; /** Write Unified header */ ! ret = AlertUnifiedAlertWriteFileHeader(file_ctx); ! if (ret != 0) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, ! "Error: AlertUnifiedLogWriteFileHeader failed"); ! return TM_ECODE_FAILED; } ! return TM_ECODE_OK; } #ifdef UNITTESTS --- 344,363 ---- snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, prefix, (uint32_t)ts.tv_sec); /* XXX filename & location */ ! l_ctx->file.fp = fopen(filename, "wb"); ! if (!l_ctx->file.fp) { ! SCLogError(SC_ERR_FOPEN, "AlertUnifiedAlertOpenFileCtx: Failed to open %s: %s", filename, strerror(errno)); ! return -1; } ! l_ctx->file.flags = 0; /** Write Unified header */ ! if (AlertUnifiedAlertWriteFileHeader(l_ctx) != 0) { ! SCLogError(SC_ERR_UNIFIED_ALERT_GENERIC, "AlertUnifiedAlertOpenFileCtx: AlertUnifiedLogWriteFileHeader failed"); ! return -1; } ! return 0; } #ifdef UNITTESTS *************** *** 391,432 **** */ static int AlertUnifiedAlertTestRotate01(void) { - int ret = 0; int r = 0; ThreadVars tv; ! LogFileCtx *lf; void *data = NULL; ! lf = AlertUnifiedAlertInitCtx(NULL); ! if (lf == NULL) return 0; ! char *filename = strdup(lf->filename); memset(&tv, 0, sizeof(ThreadVars)); ! if (lf == NULL) return 0; ! ret = AlertUnifiedAlertThreadInit(&tv, lf, &data); ! if (ret == TM_ECODE_FAILED) { ! LogFileFreeCtx(lf); return 0; } TimeSetIncrementTime(1); ! ret = AlertUnifiedAlertRotateFile(&tv, data); ! if (ret == -1) goto error; ! if (strcmp(filename, lf->filename) == 0) goto error; r = 1; error: AlertUnifiedAlertThreadDeinit(&tv, data); ! if (lf != NULL) LogFileFreeCtx(lf); return r; } #endif /* UNITTESTS */ --- 369,408 ---- */ static int AlertUnifiedAlertTestRotate01(void) { int r = 0; ThreadVars tv; ! LogCtx *l_cxt; void *data = NULL; ! l_ctx = AlertUnifiedAlertInitCtx(NULL); ! if (!lf) return 0; ! char *filename = strdup(l_ctx->file.filename); memset(&tv, 0, sizeof(ThreadVars)); ! if (!lf) return 0; ! if (AlertUnifiedAlertThreadInit(&tv, l_ctx, &data) == TM_ECODE_FAILED) { ! LogFreeCtx(l_ctx); return 0; } TimeSetIncrementTime(1); ! if (AlertUnifiedAlertRotateFile(&tv, data) == -1) goto error; ! if (strcmp(filename, l_ctx->file.filename) == 0) goto error; r = 1; error: AlertUnifiedAlertThreadDeinit(&tv, data); ! if (!lf) ! LogFreeCtx(l_ctx); return r; } #endif /* UNITTESTS */ *************** *** 434,442 **** /** * \brief this function registers unit tests for Unified2 */ ! void AlertUnifiedAlertRegisterTests (void) { #ifdef UNITTESTS ! UtRegisterTest("UnifiedAlertTestRotate01 -- Rotate File", ! AlertUnifiedAlertTestRotate01, 1); #endif /* UNITTESTS */ } --- 410,417 ---- /** * \brief this function registers unit tests for Unified2 */ ! void AlertUnifiedAlertRegisterTests(void) { #ifdef UNITTESTS ! UtRegisterTest("UnifiedAlertTestRotate01 -- Rotate File", AlertUnifiedAlertTestRotate01, 1); #endif /* UNITTESTS */ } diff -crN 1/src/alert-unified-alert.h 2/src/alert-unified-alert.h *** 1/src/alert-unified-alert.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-unified-alert.h 2010-03-11 14:45:50.565225729 +0300 *************** *** 1,10 **** /* Copyright (c) 2008 Victor Julien */ #ifndef __ALERT_UNIFIED_ALERT_H__ #define __ALERT_UNIFIED_ALERT_H__ void TmModuleAlertUnifiedAlertRegister (void); ! LogFileCtx *AlertUnifiedAlertInitCtx(ConfNode *); #endif /* __ALERT_UNIFIED_ALERT_H__ */ --- 1,11 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ #ifndef __ALERT_UNIFIED_ALERT_H__ #define __ALERT_UNIFIED_ALERT_H__ void TmModuleAlertUnifiedAlertRegister (void); ! LogCtx *AlertUnifiedAlertInitCtx(ConfNode *); #endif /* __ALERT_UNIFIED_ALERT_H__ */ diff -crN 1/src/alert-unified-log.c 2/src/alert-unified-log.c *** 1/src/alert-unified-log.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-unified-log.c 2010-03-11 14:45:50.315237253 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ /* alert unified *************** *** 49,58 **** #define MODULE_NAME "AlertUnifiedLog" ! TmEcode AlertUnifiedLog (ThreadVars *, Packet *, void *, PacketQueue *); TmEcode AlertUnifiedLogThreadInit(ThreadVars *, void *, void **); TmEcode AlertUnifiedLogThreadDeinit(ThreadVars *, void *); ! int AlertUnifiedLogOpenFileCtx(LogFileCtx *, const char *); void AlertUnifiedLogRegisterTests(void); void TmModuleAlertUnifiedLogRegister (void) { --- 50,59 ---- #define MODULE_NAME "AlertUnifiedLog" ! TmEcode AlertUnifiedLog(ThreadVars *, Packet *, void *, PacketQueue *); TmEcode AlertUnifiedLogThreadInit(ThreadVars *, void *, void **); TmEcode AlertUnifiedLogThreadDeinit(ThreadVars *, void *); ! int AlertUnifiedLogOpenFileCtx(LogCtx *, const char *); void AlertUnifiedLogRegisterTests(void); void TmModuleAlertUnifiedLogRegister (void) { *************** *** 66,73 **** } typedef struct AlertUnifiedLogThread_ { ! /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ ! LogFileCtx* file_ctx; } AlertUnifiedLogThread; #define ALERTUNIFIEDLOG_LOGMAGIC 0xDEAD1080 /* taken from Snort */ --- 67,74 ---- } typedef struct AlertUnifiedLogThread_ { ! /** LogCtx has the pointer to the file and a mutex to allow multithreading */ ! LogCtx *l_ctx; } AlertUnifiedLogThread; #define ALERTUNIFIEDLOG_LOGMAGIC 0xDEAD1080 /* taken from Snort */ *************** *** 118,131 **** uint32_t pktlen; } AlertUnifiedLogPacketHeader; ! int AlertUnifiedLogWriteFileHeader(LogFileCtx *file_ctx) { ! int ret; ! ! if (file_ctx->flags & LOGFILE_HEADER_WRITTEN) return 0; /* write the fileheader to the file so the reader can recognize it */ - AlertUnifiedLogFileHeader hdr; hdr.magic = ALERTUNIFIEDLOG_LOGMAGIC; hdr.ver_major = ALERTUNIFIEDLOG_VERMAJOR; --- 119,129 ---- uint32_t pktlen; } AlertUnifiedLogPacketHeader; ! int AlertUnifiedLogWriteFileHeader(LogCtx *l_ctx) { ! if (l_ctx->file.flags & LOGFILE_HEADER_WRITTEN) return 0; /* write the fileheader to the file so the reader can recognize it */ AlertUnifiedLogFileHeader hdr; hdr.magic = ALERTUNIFIEDLOG_LOGMAGIC; hdr.ver_major = ALERTUNIFIEDLOG_VERMAJOR; *************** *** 135,189 **** hdr.snaplen = 65536; /* XXX */ hdr.linktype = DLT_EN10MB; /* XXX */ ! ret = fwrite(&hdr, sizeof(hdr), 1, file_ctx->fp); ! if (ret != 1) { ! printf("Error: fwrite failed: ret = %" PRId32 ", %s\n", ret, strerror(errno)); return -1; } ! file_ctx->size_current = sizeof(hdr); return 0; } int AlertUnifiedLogCloseFile(ThreadVars *t, AlertUnifiedLogThread *aun) { ! if (aun->file_ctx->fp != NULL) { ! fclose(aun->file_ctx->fp); } ! aun->file_ctx->size_current = 0; ! aun->file_ctx->flags = 0; return 0; } int AlertUnifiedLogRotateFile(ThreadVars *t, AlertUnifiedLogThread *aun) { ! if (AlertUnifiedLogCloseFile(t,aun) < 0) { ! printf("Error: AlertUnifiedLogCloseFile failed\n"); return -1; } ! if (AlertUnifiedLogOpenFileCtx(aun->file_ctx,aun->file_ctx->prefix) < 0) { ! printf("Error: AlertUnifiedLogOpenFileCtx, open new log file failed\n"); return -1; } return 0; } ! TmEcode AlertUnifiedLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { AlertUnifiedLogThread *aun = (AlertUnifiedLogThread *)data; AlertUnifiedLogPacketHeader hdr; - int ret; uint8_t ethh_offset = 0; uint8_t buf[80000]; uint32_t buflen = 0; ! /* the unified1 format only supports IPv4. */ if (p->alerts.cnt == 0 || !PKT_IS_IPV4(p)) return TM_ECODE_OK; /* if we have no ethernet header (e.g. when using nfq), we have to create ! * one ourselves. */ ! if (p->ethh == NULL) { ethh_offset = sizeof(EthernetHdr); } --- 133,185 ---- hdr.snaplen = 65536; /* XXX */ hdr.linktype = DLT_EN10MB; /* XXX */ ! if (fwrite(&hdr, sizeof(hdr), 1, l_ctx->file.fp) != 1) { ! SCLogDebug("AlertUnifiedLogWriteFileHeader: write failed: %s", strerror(errno)); return -1; } ! l_ctx->file.size_current = sizeof(hdr); return 0; } int AlertUnifiedLogCloseFile(ThreadVars *t, AlertUnifiedLogThread *aun) { ! if (aun->l_ctx->file.fp) { ! fclose(aun->l_ctx->file.fp); } ! aun->l_ctx->file.size_current = 0; ! aun->l_ctx->file.flags = 0; return 0; } int AlertUnifiedLogRotateFile(ThreadVars *t, AlertUnifiedLogThread *aun) { ! if (AlertUnifiedLogCloseFile(t, aun) < 0) { ! SCLogDebug("AlertUnifiedLogRotateFile: close log file failed"); return -1; } ! if (AlertUnifiedLogOpenFileCtx(aun->l_ctx, aun->l_ctx->file.prefix) < 0) { ! SCLogDebug("Error: AlertUnifiedLogOpenFileCtx, open new log file failed"); return -1; } return 0; } ! TmEcode AlertUnifiedLog(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { AlertUnifiedLogThread *aun = (AlertUnifiedLogThread *)data; AlertUnifiedLogPacketHeader hdr; uint8_t ethh_offset = 0; uint8_t buf[80000]; uint32_t buflen = 0; ! /* the unified1 format only supports IPv4 */ if (p->alerts.cnt == 0 || !PKT_IS_IPV4(p)) return TM_ECODE_OK; /* if we have no ethernet header (e.g. when using nfq), we have to create ! * one ourselves */ ! if (!p->ethh) { ethh_offset = sizeof(EthernetHdr); } *************** *** 195,201 **** hdr.pktflags = 0; /* XXX */ hdr.pktlen = hdr.caplen = p->pktlen + ethh_offset; - uint16_t i = 0; for (; i < p->alerts.cnt; i++) { PacketAlert *pa = &p->alerts.alerts[i]; --- 191,196 ---- *************** *** 210,252 **** memcpy(buf,&hdr,sizeof(hdr)); buflen = sizeof(hdr); ! if (p->ethh == NULL) { EthernetHdr ethh; memset(ðh, 0, sizeof(EthernetHdr)); ethh.eth_type = htons(ETHERNET_TYPE_IP); ! memcpy(buf+buflen,ðh,sizeof(ethh)); buflen += sizeof(ethh); } ! memcpy(buf+buflen,&p->pkt,p->pktlen); buflen += p->pktlen; /** Wait for the mutex. We dont want all the threads rotating the file * at the same time :) */ ! SCMutexLock(&aun->file_ctx->fp_mutex); ! if ((aun->file_ctx->size_current + sizeof(hdr) + p->pktlen + ethh_offset) > aun->file_ctx->size_limit) { ! if (AlertUnifiedLogRotateFile(tv,aun) < 0) { ! SCMutexUnlock(&aun->file_ctx->fp_mutex); ! aun->file_ctx->alerts += i; return TM_ECODE_FAILED; } } ! ret = fwrite(buf, buflen, 1, aun->file_ctx->fp); ! if (ret != 1) { ! printf("Error: fwrite failed: %s\n", strerror(errno)); ! aun->file_ctx->alerts += i; ! SCMutexUnlock(&aun->file_ctx->fp_mutex); return TM_ECODE_FAILED; } /* force writing to disk so barnyard will not read half * written records and choke. */ ! fflush(aun->file_ctx->fp); ! aun->file_ctx->alerts++; ! aun->file_ctx->size_current += buflen; ! SCMutexUnlock(&aun->file_ctx->fp_mutex); } return TM_ECODE_OK; --- 205,246 ---- memcpy(buf,&hdr,sizeof(hdr)); buflen = sizeof(hdr); ! if (!p->ethh) { EthernetHdr ethh; memset(ðh, 0, sizeof(EthernetHdr)); ethh.eth_type = htons(ETHERNET_TYPE_IP); ! memcpy(buf + buflen, ðh, sizeof(ethh)); buflen += sizeof(ethh); } ! memcpy(buf + buflen, &p->pkt, p->pktlen); buflen += p->pktlen; /** Wait for the mutex. We dont want all the threads rotating the file * at the same time :) */ ! SCMutexLock(&aun->l_ctx->file.fp_mutex); ! if ((aun->l_ctx->file.size_current + sizeof(hdr) + p->pktlen + ethh_offset) > aun->l_ctx->file.size_limit) { ! if (AlertUnifiedLogRotateFile(tv, aun) < 0) { ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); ! aun->l_ctx->alerts += i; return TM_ECODE_FAILED; } } ! if (fwrite(buf, buflen, 1, aun->l_ctx->file.fp) != 1) { ! printf("AlertUnifiedLog: write failed: %s", strerror(errno)); ! aun->l_ctx->alerts += i; ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); return TM_ECODE_FAILED; } /* force writing to disk so barnyard will not read half * written records and choke. */ ! fflush(aun->l_ctx->file.fp); ! aun->l_ctx->file.size_current += buflen; ! aun->l_ctx->alerts++; ! SCMutexUnlock(&aun->l_ctx->file.fp_mutex); } return TM_ECODE_OK; *************** *** 255,272 **** TmEcode AlertUnifiedLogThreadInit(ThreadVars *t, void *initdata, void **data) { AlertUnifiedLogThread *aun = malloc(sizeof(AlertUnifiedLogThread)); ! if (aun == NULL) { return TM_ECODE_FAILED; - } memset(aun, 0, sizeof(AlertUnifiedLogThread)); ! if (initdata == NULL) { ! SCLogDebug("Error getting context for UnifiedLog. \"initdata\" argument NULL"); free(aun); return TM_ECODE_FAILED; } /** Use the Ouptut Context (file pointer and mutex) */ ! aun->file_ctx = (LogFileCtx*) initdata; *data = (void *)aun; return TM_ECODE_OK; --- 249,266 ---- TmEcode AlertUnifiedLogThreadInit(ThreadVars *t, void *initdata, void **data) { AlertUnifiedLogThread *aun = malloc(sizeof(AlertUnifiedLogThread)); ! if (!aun) return TM_ECODE_FAILED; memset(aun, 0, sizeof(AlertUnifiedLogThread)); ! if (!initdata) { ! SCLogDebug("AlertUnifiedLogThreadInit: Error getting context for UnifiedLog. \"initdata\" argument is NULL"); free(aun); return TM_ECODE_FAILED; } + /** Use the Ouptut Context (file pointer and mutex) */ ! aun->l_ctx = (LogCtx*)initdata; *data = (void *)aun; return TM_ECODE_OK; *************** *** 275,372 **** TmEcode AlertUnifiedLogThreadDeinit(ThreadVars *t, void *data) { AlertUnifiedLogThread *aun = (AlertUnifiedLogThread *)data; ! if (aun == NULL) { ! goto error; ! } ! if (!(aun->file_ctx->flags & LOGFILE_ALERTS_PRINTED)) { ! SCLogInfo("Alert unified 1 log module wrote %"PRIu64" alerts", aun->file_ctx->alerts); /* Do not print it for each thread */ ! aun->file_ctx->flags |= LOGFILE_ALERTS_PRINTED; } /* clear memory */ memset(aun, 0, sizeof(AlertUnifiedLogThread)); free(aun); return TM_ECODE_OK; - - error: - - return TM_ECODE_FAILED; } ! ! /** \brief Create a new LogFileCtx for unified alert logging. * \param ConfNode pointer to the configuration node for this logger. ! * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ ! LogFileCtx *AlertUnifiedLogInitCtx(ConfNode *conf) { ! int ret = 0; ! LogFileCtx* file_ctx=LogFileNewCtx(); ! ! if (file_ctx == NULL) { ! printf("AlertUnifiedLogInitCtx: Couldn't create new file_ctx\n"); return NULL; } ! const char *filename = NULL; ! if (conf != NULL) { /* \todo Maybe test should setup a ConfNode */ ! filename = ConfNodeLookupChildValue(conf, "filename"); ! } ! if (filename == NULL) filename = DEFAULT_LOG_FILENAME; ! file_ctx->prefix = strdup(filename); - const char *s_limit = NULL; uint32_t limit = DEFAULT_LIMIT; ! if (conf != NULL) { ! s_limit = ConfNodeLookupChildValue(conf, "limit"); ! if (s_limit != NULL) { ! if (ByteExtractStringUint32(&limit, 10, 0, s_limit) == -1) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, ! "Fail to initialize unified log output, invalid limit: %s", ! s_limit); ! exit(EXIT_FAILURE); ! } ! if (limit < MIN_LIMIT) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, ! "Fail to initialize unified log output, limit less than " ! "allowed minimum."); ! exit(EXIT_FAILURE); ! } ! SCLogDebug("limit set to %"PRIu32, limit); } } ! file_ctx->size_limit = limit * 1024 * 1024; ! ret = AlertUnifiedLogOpenFileCtx(file_ctx, filename); ! if (ret < 0) return NULL; ! SCLogInfo("Unified-log initialized: filename %s, limit %"PRIu32" MB", ! filename, limit); ! return file_ctx; } ! /** \brief Read the config set the file pointer, open the file ! * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() ! * \param prefix Prefix for log filenames. ! * \return -1 if failure, 0 if succesful * */ ! int AlertUnifiedLogOpenFileCtx(LogFileCtx *file_ctx, const char *prefix) { ! int ret = 0; ! char *filename = NULL; ! if (file_ctx->filename != NULL) ! filename = file_ctx->filename; else ! filename = file_ctx->filename = malloc(PATH_MAX); /* XXX some sane default? */ /* get the time so we can have a filename with seconds since epoch */ struct timeval ts; ! memset (&ts, 0, sizeof(struct timeval)); extern int run_mode; if (run_mode == MODE_UNITTEST) --- 269,345 ---- TmEcode AlertUnifiedLogThreadDeinit(ThreadVars *t, void *data) { AlertUnifiedLogThread *aun = (AlertUnifiedLogThread *)data; ! if (!aun) ! return TM_ECODE_FAILED; ! if (!(aun->l_ctx->file.flags & LOGFILE_ALERTS_PRINTED)) { ! SCLogInfo("AlertUnifiedLogThreadDeinit: Alert unified log module wrote %" PRIu64 " alerts", aun->l_ctx->alerts); /* Do not print it for each thread */ ! aun->l_ctx->file.flags |= LOGFILE_ALERTS_PRINTED; } /* clear memory */ memset(aun, 0, sizeof(AlertUnifiedLogThread)); free(aun); return TM_ECODE_OK; } ! /** \brief Create a new LogCtx for unified alert logging. * \param ConfNode pointer to the configuration node for this logger. ! * \return NULL if failure, LogCtx* to the l_ctx if succesful * */ ! LogCtx *AlertUnifiedLogInitCtx(ConfNode *conf) { ! LogCtx *l_ctx = LogNewCtx(); ! if (!l_ctx) { ! SCLogError(SC_ERR_UNIFIED_LOG_GENERIC, "Could not create new output context"); return NULL; } ! const char *filename = ConfNodeLookupChildValue(conf, "filename"); ! if (!filename) filename = DEFAULT_LOG_FILENAME; ! l_ctx->file.prefix = strdup(filename); uint32_t limit = DEFAULT_LIMIT; ! const char *s_limit = ConfNodeLookupChildValue(conf, "limit"); ! if (s_limit != NULL) { ! if (ByteExtractStringUint32(&limit, 10, 0, s_limit) == -1) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, "Fail to initialize unified log output, invalid limit: %s", s_limit); ! exit(EXIT_FAILURE); ! } ! if (limit < MIN_LIMIT) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, "Fail to initialize unified log output, limit less than allowed minimum"); ! exit(EXIT_FAILURE); } } ! l_ctx->file.size_limit = limit * 1024 * 1024; ! if (AlertUnifiedLogOpenFileCtx(l_ctx, filename) < 0) return NULL; ! SCLogInfo("Unified-log initialized: filename %s, limit %" PRIu32 " MB", filename, limit); ! return l_ctx; } ! /** ! * \brief Read the config set the file pointer, open the file ! * \param l_ctx pointer to a created LogCtx using LogNewCtx() ! * \param prefix Prefix for log filenames. ! * \return -1 if failure, 0 if succesful * */ ! int AlertUnifiedLogOpenFileCtx(LogCtx *l_ctx, const char *prefix) { ! char *filename; ! if (l_ctx->file.filename) ! filename = l_ctx->file.filename; else ! filename = l_ctx->file.filename = malloc(PATH_MAX); /* XXX some sane default? */ /* get the time so we can have a filename with seconds since epoch */ struct timeval ts; ! memset(&ts, 0, sizeof(struct timeval)); extern int run_mode; if (run_mode == MODE_UNITTEST) *************** *** 382,402 **** snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, prefix, (uint32_t)ts.tv_sec); /* XXX filename & location */ ! file_ctx->fp = fopen(filename, "wb"); ! if (file_ctx->fp == NULL) { ! SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", filename, ! strerror(errno)); ! ret = -1; } /** Write Unified header */ ! ret = AlertUnifiedLogWriteFileHeader(file_ctx); ! if (ret != 0) { ! printf("Error: AlertUnifiedLogWriteFileHeader failed.\n"); ! return TM_ECODE_FAILED; } ! return TM_ECODE_OK; } #ifdef UNITTESTS --- 355,373 ---- snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, prefix, (uint32_t)ts.tv_sec); /* XXX filename & location */ ! l_ctx->file.fp = fopen(filename, "wb"); ! if (!l_ctx->file.fp) { ! SCLogError(SC_ERR_FOPEN, "Failed to open %s: %s", filename, strerror(errno)); ! return -1; } /** Write Unified header */ ! if (AlertUnifiedLogWriteFileHeader(l_ctx) != 0) { ! SCLogError(SC_ERR_UNIFIED_LOG_GENERIC, "Failed to write header"); ! return -1; } ! return 0; } #ifdef UNITTESTS *************** *** 408,449 **** */ static int AlertUnifiedLogTestRotate01(void) { - int ret = 0; int r = 0; ThreadVars tv; ! LogFileCtx *lf; void *data = NULL; ! lf = AlertUnifiedLogInitCtx(NULL); ! if (lf == NULL) return 0; ! char *filename = strdup(lf->filename); memset(&tv, 0, sizeof(ThreadVars)); ! if (lf == NULL) return 0; ! ret = AlertUnifiedLogThreadInit(&tv, lf, &data); ! if (ret == TM_ECODE_FAILED) { ! LogFileFreeCtx(lf); return 0; } TimeSetIncrementTime(1); ! ret = AlertUnifiedLogRotateFile(&tv, data); ! if (ret == -1) goto error; ! if (strcmp(filename, lf->filename) == 0) goto error; r = 1; error: AlertUnifiedLogThreadDeinit(&tv, data); ! if (lf != NULL) LogFileFreeCtx(lf); return r; } #endif /* UNITTESTS */ --- 379,418 ---- */ static int AlertUnifiedLogTestRotate01(void) { int r = 0; ThreadVars tv; ! LogCtx *l_ctx; void *data = NULL; ! l_ctx = AlertUnifiedLogInitCtx(NULL); ! if (!l_ctx) return 0; ! char *filename = strdup(l_cxt->file.filename); memset(&tv, 0, sizeof(ThreadVars)); ! if (!lf) return 0; ! if (AlertUnifiedLogThreadInit(&tv, lf, &data) == TM_ECODE_FAILED) { ! LogFreeCtx(l_ctx); return 0; } TimeSetIncrementTime(1); ! if (AlertUnifiedLogRotateFile(&tv, data) == -1) goto error; ! if (strcmp(filename, l_ctx->file.filename) == 0) goto error; r = 1; error: AlertUnifiedLogThreadDeinit(&tv, data); ! if (!l_ctx) ! LogFreeCtx(l_ctx); return r; } #endif /* UNITTESTS */ *************** *** 451,460 **** /** * \brief this function registers unit tests for Unified2 */ ! void AlertUnifiedLogRegisterTests (void) { #ifdef UNITTESTS ! UtRegisterTest("UnifiedAlertTestRotate01 -- Rotate File", ! AlertUnifiedLogTestRotate01, 1); #endif /* UNITTESTS */ } - --- 420,427 ---- /** * \brief this function registers unit tests for Unified2 */ ! void AlertUnifiedLogRegisterTests(void) { #ifdef UNITTESTS ! UtRegisterTest("UnifiedAlertTestRotate01 -- Rotate File", AlertUnifiedLogTestRotate01, 1); #endif /* UNITTESTS */ } diff -crN 1/src/alert-unified-log.h 2/src/alert-unified-log.h *** 1/src/alert-unified-log.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/alert-unified-log.h 2010-03-11 14:45:50.827211271 +0300 *************** *** 1,10 **** /* Copyright (c) 2008 Victor Julien */ #ifndef __ALERT_UNIFIED_LOG_H__ #define __ALERT_UNIFIED_LOG_H__ void TmModuleAlertUnifiedLogRegister (void); ! LogFileCtx *AlertUnifiedLogInitCtx(ConfNode *); #endif /* __ALERT_UNIFIED_LOG_H__ */ --- 1,11 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ #ifndef __ALERT_UNIFIED_LOG_H__ #define __ALERT_UNIFIED_LOG_H__ void TmModuleAlertUnifiedLogRegister (void); ! LogCtx *AlertUnifiedLogInitCtx(ConfNode *); #endif /* __ALERT_UNIFIED_LOG_H__ */ diff -crN 1/src/log-httplog.c 2/src/log-httplog.c *** 1/src/log-httplog.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/log-httplog.c 2010-03-11 14:45:50.445225729 +0300 *************** *** 1,7 **** /* Copyright (c) 2008 Victor Julien */ ! /* httplog ! * */ #include "suricata-common.h" --- 1,8 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ ! /* ! * httplog */ #include "suricata-common.h" *************** *** 36,42 **** TmEcode LogHttpLogThreadInit(ThreadVars *, void *, void **); TmEcode LogHttpLogThreadDeinit(ThreadVars *, void *); void LogHttpLogExitPrintStats(ThreadVars *, void *); ! int LogHttpLogOpenFileCtx(LogFileCtx* , const char *); void TmModuleLogHttpLogRegister (void) { tmm_modules[TMM_LOGHTTPLOG].name = MODULE_NAME; --- 37,43 ---- TmEcode LogHttpLogThreadInit(ThreadVars *, void *, void **); TmEcode LogHttpLogThreadDeinit(ThreadVars *, void *); void LogHttpLogExitPrintStats(ThreadVars *, void *); ! int LogHttpLogOpenFileCtx(LogCtx* , const char *); void TmModuleLogHttpLogRegister (void) { tmm_modules[TMM_LOGHTTPLOG].name = MODULE_NAME; *************** *** 68,79 **** } typedef struct LogHttpLogThread_ { ! LogFileCtx *file_ctx; ! /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ uint32_t uri_cnt; } LogHttpLogThread; ! static void CreateTimeString (const struct timeval *ts, char *str, size_t size) { time_t time = ts->tv_sec; struct tm *t = gmtime(&time); uint32_t sec = ts->tv_sec % 86400; --- 69,81 ---- } typedef struct LogHttpLogThread_ { ! LogCtx *l_ctx; ! /** LogCtx has the pointer to the file and a mutex to allow multithreading */ uint32_t uri_cnt; } LogHttpLogThread; ! static void CreateTimeString(const struct timeval *ts, char *str, size_t size) ! { time_t time = ts->tv_sec; struct tm *t = gmtime(&time); uint32_t sec = ts->tv_sec % 86400; *************** *** 92,100 **** uint8_t i = 0; /* no flow, no htp state */ ! if (p->flow == NULL) { SCReturnInt(TM_ECODE_OK); - } /* check if we have HTTP state or not */ SCMutexLock(&p->flow->m); --- 94,101 ---- uint8_t i = 0; /* no flow, no htp state */ ! if (!p->flow) SCReturnInt(TM_ECODE_OK); /* check if we have HTTP state or not */ SCMutexLock(&p->flow->m); *************** *** 103,118 **** goto end; HtpState *htp_state = (HtpState *)AppLayerGetProtoStateFromPacket(p); ! if (htp_state == NULL) { ! SCLogDebug("no http state, so no request logging"); goto end; } ! if (htp_state->connp == NULL) goto end; if (!(htp_state->flags & HTP_FLAG_NEW_REQUEST)) { ! SCLogDebug("no new http request , so no request logging"); goto end; } htp_tx_t *tx = NULL; --- 104,119 ---- goto end; HtpState *htp_state = (HtpState *)AppLayerGetProtoStateFromPacket(p); ! if (!htp_state) { ! SCLogDebug("LogHttpLogIPv4: No http state, so no request logging"); goto end; } ! if (!htp_state->connp) goto end; if (!(htp_state->flags & HTP_FLAG_NEW_REQUEST)) { ! SCLogDebug("LogHttpLogIPv4: No new http request, so no request logging"); goto end; } htp_tx_t *tx = NULL; *************** *** 134,192 **** dp = p->sp; } ! SCMutexLock(&aft->file_ctx->fp_mutex); ! for (i = htp_state->new_in_tx_index; ! i < list_size(htp_state->connp->conn->transactions); i++) { tx = list_get(htp_state->connp->conn->transactions, i); ! if (tx == NULL) { ! SCLogDebug("tx is NULL not logging !!"); continue; } ! SCLogDebug("got a HTTP request and now logging !!"); /* time */ ! fprintf(aft->file_ctx->fp, "%s ", timebuf); /* hostname */ ! if (tx->parsed_uri != NULL && ! tx->parsed_uri->hostname != NULL) ! { ! PrintRawUriFp(aft->file_ctx->fp, (uint8_t *)bstr_ptr(tx->parsed_uri->hostname), bstr_len(tx->parsed_uri->hostname)); ! } else { ! fprintf(aft->file_ctx->fp, ""); ! } ! fprintf(aft->file_ctx->fp, " [**] "); /* uri */ if (tx->request_uri != NULL) { ! PrintRawUriFp(aft->file_ctx->fp, (uint8_t *)bstr_ptr(tx->request_uri), bstr_len(tx->request_uri)); } ! fprintf(aft->file_ctx->fp, " [**] "); /* user agent */ htp_header_t *h_user_agent = table_getc(tx->request_headers, "user-agent"); ! if (h_user_agent != NULL) { ! PrintRawUriFp(aft->file_ctx->fp, (uint8_t *)bstr_ptr(h_user_agent->value), bstr_len(h_user_agent->value)); ! } else { ! fprintf(aft->file_ctx->fp, ""); ! } /* ip/tcp header info */ ! fprintf(aft->file_ctx->fp, " [**] %s:%" PRIu32 " -> %s:%" PRIu32 "\n", ! srcip, sp, dstip, dp); } - fflush(aft->file_ctx->fp); - SCMutexUnlock(&aft->file_ctx->fp_mutex); ! aft->uri_cnt += list_size(htp_state->connp->conn->transactions) - ! htp_state->new_in_tx_index; htp_state->flags &= ~HTP_FLAG_NEW_REQUEST; end: SCMutexUnlock(&p->flow->m); --- 135,187 ---- dp = p->sp; } ! SCMutexLock(&aft->l_ctx->file.fp_mutex); ! for (i = htp_state->new_in_tx_index; i < list_size(htp_state->connp->conn->transactions); i++) { tx = list_get(htp_state->connp->conn->transactions, i); ! if (!tx) { ! SCLogDebug("LogHttpLogIPv4: stx is NULL not logging !!"); continue; } ! SCLogDebug("LogHttpLogIPv4: got a HTTP request and now logging !!"); /* time */ ! fprintf(aft->l_ctx->file.fp, "%s ", timebuf); /* hostname */ ! if (tx->parsed_uri && tx->parsed_uri->hostname) { ! PrintRawUriFp(aft->l_ctx->file.fp, (uint8_t *)bstr_ptr(tx->parsed_uri->hostname), bstr_len(tx->parsed_uri->hostname)); ! } else ! fprintf(aft->l_ctx->file.fp, ""); ! fprintf(aft->l_ctx->file.fp, " [**] "); /* uri */ if (tx->request_uri != NULL) { ! PrintRawUriFp(aft->l_ctx->file.fp, (uint8_t *)bstr_ptr(tx->request_uri), bstr_len(tx->request_uri)); } ! fprintf(aft->l_ctx->file.fp, " [**] "); /* user agent */ htp_header_t *h_user_agent = table_getc(tx->request_headers, "user-agent"); ! if (h_user_agent) { ! PrintRawUriFp(aft->l_ctx->file.fp, (uint8_t *)bstr_ptr(h_user_agent->value), bstr_len(h_user_agent->value)); ! } else ! fprintf(aft->l_ctx->file.fp, ""); /* ip/tcp header info */ ! fprintf(aft->l_ctx->file.fp, " [**] %s:%" PRIu32 " -> %s:%" PRIu32 "\n", srcip, sp, dstip, dp); } ! fflush(aft->l_ctx->file.fp); ! SCMutexUnlock(&aft->l_ctx->file.fp_mutex); ! ! aft->uri_cnt += list_size(htp_state->connp->conn->transactions) - htp_state->new_in_tx_index; htp_state->flags &= ~HTP_FLAG_NEW_REQUEST; end: SCMutexUnlock(&p->flow->m); *************** *** 201,207 **** uint8_t i = 0; /* no flow, no htp state */ ! if (p->flow == NULL) { SCReturnInt(TM_ECODE_OK); } --- 196,202 ---- uint8_t i = 0; /* no flow, no htp state */ ! if (!p->flow) { SCReturnInt(TM_ECODE_OK); } *************** *** 212,227 **** goto end; HtpState *htp_state = (HtpState *)AppLayerGetProtoStateFromPacket(p); ! if (htp_state == NULL) { ! SCLogDebug("no http state, so no request logging"); goto end; } ! if (htp_state->connp == NULL) goto end; if (!(htp_state->flags & HTP_FLAG_NEW_REQUEST)) { ! SCLogDebug("no new http request , so no request logging"); goto end; } htp_tx_t *tx = NULL; --- 207,222 ---- goto end; HtpState *htp_state = (HtpState *)AppLayerGetProtoStateFromPacket(p); ! if (!htp_state) { ! SCLogDebug("LogHttpLogIPv6: No http state, so no request logging"); goto end; } ! if (!htp_state->connp) goto end; if (!(htp_state->flags & HTP_FLAG_NEW_REQUEST)) { ! SCLogDebug("LogHttpLogIPv6: No new http request, so no request logging"); goto end; } htp_tx_t *tx = NULL; *************** *** 243,325 **** sp = p->dp; dp = p->sp; } ! SCMutexLock(&aft->file_ctx->fp_mutex); ! for (i = htp_state->new_in_tx_index; ! i < list_size(htp_state->connp->conn->transactions); i++) ! { tx = list_get(htp_state->connp->conn->transactions, i); ! if (tx == NULL) { ! SCLogDebug("tx is NULL not logging !!"); continue; } ! SCLogDebug("got a HTTP request and now logging !!"); /* time */ ! fprintf(aft->file_ctx->fp, "%s ", timebuf); /* hostname */ ! if (tx->parsed_uri != NULL && ! tx->parsed_uri->hostname != NULL) ! { ! PrintRawUriFp(aft->file_ctx->fp, ! (uint8_t *)bstr_ptr(tx->parsed_uri->hostname), ! bstr_len(tx->parsed_uri->hostname)); ! } else { ! fprintf(aft->file_ctx->fp, ""); ! } ! fprintf(aft->file_ctx->fp, " [**] "); /* uri */ ! if (tx->request_uri != NULL) { ! PrintRawUriFp(aft->file_ctx->fp, ! (uint8_t *)bstr_ptr(tx->request_uri), ! bstr_len(tx->request_uri)); ! } ! fprintf(aft->file_ctx->fp, " [**] "); /* user agent */ htp_header_t *h_user_agent = table_getc(tx->request_headers, "user-agent"); ! if (h_user_agent != NULL) { ! PrintRawUriFp(aft->file_ctx->fp, ! (uint8_t *)bstr_ptr(h_user_agent->value), ! bstr_len(h_user_agent->value)); ! } else { ! fprintf(aft->file_ctx->fp, ""); ! } /* ip/tcp header info */ ! fprintf(aft->file_ctx->fp, " [**] %s:%" PRIu32 " -> %s:%" PRIu32 "\n", ! srcip, sp, dstip, dp); } - fflush(aft->file_ctx->fp); - SCMutexUnlock(&aft->file_ctx->fp_mutex); ! aft->uri_cnt += list_size(htp_state->connp->conn->transactions) - ! htp_state->new_in_tx_index; htp_state->flags &= ~HTP_FLAG_NEW_REQUEST; end: SCMutexUnlock(&p->flow->m); SCReturnInt(TM_ECODE_OK); } ! TmEcode LogHttpLog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { SCEnter(); /* no flow, no htp state */ ! if (p->flow == NULL) { SCReturnInt(TM_ECODE_OK); - } ! if (!(PKT_IS_TCP(p))) { SCReturnInt(TM_ECODE_OK); - } ! if (PKT_IS_IPV4(p)) { SCReturnInt(LogHttpLogIPv4(tv, p, data, pq)); ! } else if (PKT_IS_IPV6(p)) { SCReturnInt(LogHttpLogIPv6(tv, p, data, pq)); - } SCReturnInt(TM_ECODE_OK); } --- 238,303 ---- sp = p->dp; dp = p->sp; } ! SCMutexLock(&aft->l_ctx->file.fp_mutex); ! for (i = htp_state->new_in_tx_index; i < list_size(htp_state->connp->conn->transactions); i++) { tx = list_get(htp_state->connp->conn->transactions, i); ! if (!tx) { ! SCLogDebug("LogHttpLogIPv6: TX is NULL, not logging!"); continue; } ! SCLogDebug("LogHttpLogIPv6: Got a HTTP request and now logging!"); /* time */ ! fprintf(aft->l_ctx->file.fp, "%s ", timebuf); /* hostname */ ! if (tx->parsed_uri && tx->parsed_uri->hostname) ! PrintRawUriFp(aft->l_ctx->file.fp, (uint8_t *)bstr_ptr(tx->parsed_uri->hostname), bstr_len(tx->parsed_uri->hostname)); ! else ! fprintf(aft->l_ctx->file.fp, ""); ! fprintf(aft->l_ctx->file.fp, " [**] "); /* uri */ ! if (tx->request_uri) ! PrintRawUriFp(aft->l_ctx->file.fp, (uint8_t *)bstr_ptr(tx->request_uri), bstr_len(tx->request_uri)); ! fprintf(aft->l_ctx->file.fp, " [**] "); /* user agent */ htp_header_t *h_user_agent = table_getc(tx->request_headers, "user-agent"); ! if (h_user_agent) ! PrintRawUriFp(aft->l_ctx->file.fp, (uint8_t *)bstr_ptr(h_user_agent->value), bstr_len(h_user_agent->value)); ! else ! fprintf(aft->l_ctx->file.fp, ""); /* ip/tcp header info */ ! fprintf(aft->l_ctx->file.fp, " [**] %s:%" PRIu32 " -> %s:%" PRIu32 "\n", srcip, sp, dstip, dp); } ! fflush(aft->l_ctx->file.fp); ! SCMutexUnlock(&aft->l_ctx->file.fp_mutex); ! ! aft->uri_cnt += list_size(htp_state->connp->conn->transactions) - htp_state->new_in_tx_index; htp_state->flags &= ~HTP_FLAG_NEW_REQUEST; end: SCMutexUnlock(&p->flow->m); SCReturnInt(TM_ECODE_OK); } ! TmEcode LogHttpLog(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { SCEnter(); /* no flow, no htp state */ ! if (!p->flow) SCReturnInt(TM_ECODE_OK); ! if (!(PKT_IS_TCP(p))) SCReturnInt(TM_ECODE_OK); ! if (PKT_IS_IPV4(p)) SCReturnInt(LogHttpLogIPv4(tv, p, data, pq)); ! else if (PKT_IS_IPV6(p)) SCReturnInt(LogHttpLogIPv6(tv, p, data, pq)); SCReturnInt(TM_ECODE_OK); } *************** *** 327,345 **** TmEcode LogHttpLogThreadInit(ThreadVars *t, void *initdata, void **data) { LogHttpLogThread *aft = malloc(sizeof(LogHttpLogThread)); ! if (aft == NULL) { return TM_ECODE_FAILED; - } memset(aft, 0, sizeof(LogHttpLogThread)); ! if(initdata == NULL) ! { ! SCLogDebug("Error getting context for HTTPLog. \"initdata\" argument NULL"); free(aft); return TM_ECODE_FAILED; } /** Use the Ouptut Context (file pointer and mutex) */ ! aft->file_ctx=(LogFileCtx*) initdata; *data = (void *)aft; return TM_ECODE_OK; --- 305,322 ---- TmEcode LogHttpLogThreadInit(ThreadVars *t, void *initdata, void **data) { LogHttpLogThread *aft = malloc(sizeof(LogHttpLogThread)); ! if (!aft) return TM_ECODE_FAILED; memset(aft, 0, sizeof(LogHttpLogThread)); ! if (!initdata) { ! SCLogDebug("Error getting context for HTTPLog. \"initdata\" argument NULL"); free(aft); return TM_ECODE_FAILED; } + /** Use the Ouptut Context (file pointer and mutex) */ ! aft->l_ctx = (LogCtx*)initdata; *data = (void *)aft; return TM_ECODE_OK; *************** *** 348,358 **** TmEcode LogHttpLogThreadDeinit(ThreadVars *t, void *data) { LogHttpLogThread *aft = (LogHttpLogThread *)data; ! if (aft == NULL) { return TM_ECODE_OK; - } - - /* clear memory */ memset(aft, 0, sizeof(LogHttpLogThread)); free(aft); --- 325,332 ---- TmEcode LogHttpLogThreadDeinit(ThreadVars *t, void *data) { LogHttpLogThread *aft = (LogHttpLogThread *)data; ! if (!aft) return TM_ECODE_OK; memset(aft, 0, sizeof(LogHttpLogThread)); free(aft); *************** *** 361,423 **** void LogHttpLogExitPrintStats(ThreadVars *tv, void *data) { LogHttpLogThread *aft = (LogHttpLogThread *)data; ! if (aft == NULL) { return; - } SCLogInfo("(%s) HTTP requests %" PRIu32 "", tv->name, aft->uri_cnt); } ! /** \brief Create a new http log LogFileCtx. ! * \param conf Pointer to ConfNode containing this loggers configuration. ! * \return NULL if failure, LogFileCtx* to the file_ctx if succesful ! * */ ! LogFileCtx *LogHttpLogInitCtx(ConfNode *conf) { ! int ret=0; ! LogFileCtx* file_ctx=LogFileNewCtx(); ! ! if(file_ctx == NULL) ! { ! SCLogError(SC_ERR_HTTP_LOG_GENERIC, "LogHttpLogInitCtx: Couldn't " ! "create new file_ctx"); return NULL; } const char *filename = ConfNodeLookupChildValue(conf, "filename"); ! if (filename == NULL) filename = DEFAULT_LOG_FILENAME; ! /** fill the new LogFileCtx with the specific LogHttpLog configuration */ ! ret=LogHttpLogOpenFileCtx(file_ctx, filename); ! ! if(ret < 0) return NULL; ! return file_ctx; } ! /** \brief Read the config set the file pointer, open the file ! * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() ! * \param config_file for loading separate configs ! * \return -1 if failure, 0 if succesful ! * */ ! int LogHttpLogOpenFileCtx(LogFileCtx *file_ctx, const char *filename) { char log_path[PATH_MAX], *log_dir; if (ConfGet("default-log-dir", &log_dir) != 1) log_dir = DEFAULT_LOG_DIR; snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); ! file_ctx->fp = fopen(log_path, "w"); ! ! if (file_ctx->fp == NULL) { ! SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", log_path, ! strerror(errno)); return -1; } return 0; } - - --- 335,388 ---- void LogHttpLogExitPrintStats(ThreadVars *tv, void *data) { LogHttpLogThread *aft = (LogHttpLogThread *)data; ! if (!aft) return; SCLogInfo("(%s) HTTP requests %" PRIu32 "", tv->name, aft->uri_cnt); } ! /** ! * \brief Create a new http log LogCtx. ! * \param conf Pointer to ConfNode containing this loggers configuration. ! * \return NULL if failure, LogCtx pointer to the l_ctx if succesful ! */ ! LogCtx *LogHttpLogInitCtx(ConfNode *conf) { ! LogCtx* l_ctx = LogNewCtx(); ! if (!l_ctx) { ! SCLogError(SC_ERR_HTTP_LOG_GENERIC, "Could not create new output context"); return NULL; } const char *filename = ConfNodeLookupChildValue(conf, "filename"); ! if (!filename) filename = DEFAULT_LOG_FILENAME; ! /** fill the new LogCtx with the specific LogHttpLog configuration */ ! if (LogHttpLogOpenFileCtx(l_ctx, filename) < 0) return NULL; ! return l_ctx; } ! /** ! * \brief Read the config set the file pointer, open the file ! * \param l_ctx pointer to a created LogCtx using LogNewCtx() ! * \param config_file for loading separate configs ! * \return -1 if failure, 0 if succesful ! */ ! int LogHttpLogOpenFileCtx(LogCtx *l_ctx, const char *filename) { char log_path[PATH_MAX], *log_dir; if (ConfGet("default-log-dir", &log_dir) != 1) log_dir = DEFAULT_LOG_DIR; snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); ! l_ctx->file.fp = fopen(log_path, "w"); ! if (l_ctx->file.fp) { ! SCLogError(SC_ERR_FOPEN, "Failed to open %s: %s", log_path, strerror(errno)); return -1; } return 0; } diff -crN 1/src/log-httplog.h 2/src/log-httplog.h *** 1/src/log-httplog.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/log-httplog.h 2010-03-11 14:45:50.671226078 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ #ifndef __LOG_HTTPLOG_H__ *************** *** 6,12 **** void TmModuleLogHttpLogRegister (void); void TmModuleLogHttpLogIPv4Register (void); void TmModuleLogHttpLogIPv6Register (void); ! LogFileCtx *LogHttpLogInitCtx(ConfNode *); #endif /* __LOG_HTTPLOG_H__ */ --- 7,13 ---- void TmModuleLogHttpLogRegister (void); void TmModuleLogHttpLogIPv4Register (void); void TmModuleLogHttpLogIPv6Register (void); ! LogCtx *LogHttpLogInitCtx(ConfNode *); #endif /* __LOG_HTTPLOG_H__ */ diff -crN 1/src/Makefile.am 2/src/Makefile.am *** 1/src/Makefile.am 2010-02-19 20:47:52.000000000 +0300 --- 2/src/Makefile.am 2010-03-11 14:45:51.115237392 +0300 *************** *** 161,166 **** --- 161,167 ---- alert-unified-log.c alert-unified-log.h \ alert-unified-alert.c alert-unified-alert.h \ alert-unified2-alert.c alert-unified2-alert.h \ + alert-pgsql-log.c alert-pgsql-log.h \ log-httplog.c log-httplog.h \ stream.c stream.h \ stream-tcp.c stream-tcp.h stream-tcp-private.h \ diff -crN 1/src/Makefile.in 2/src/Makefile.in *** 1/src/Makefile.in 2010-02-19 20:48:18.000000000 +0300 --- 2/src/Makefile.in 2010-03-11 14:45:50.636211411 +0300 *************** *** 128,134 **** alert-fastlog.$(OBJEXT) alert-debuglog.$(OBJEXT) \ alert-prelude.$(OBJEXT) alert-unified-log.$(OBJEXT) \ alert-unified-alert.$(OBJEXT) alert-unified2-alert.$(OBJEXT) \ ! log-httplog.$(OBJEXT) stream.$(OBJEXT) stream-tcp.$(OBJEXT) \ stream-tcp-reassemble.$(OBJEXT) respond-reject.$(OBJEXT) \ respond-reject-libnet11.$(OBJEXT) conf.$(OBJEXT) \ conf-yaml-loader.$(OBJEXT) counters.$(OBJEXT) \ --- 128,135 ---- alert-fastlog.$(OBJEXT) alert-debuglog.$(OBJEXT) \ alert-prelude.$(OBJEXT) alert-unified-log.$(OBJEXT) \ alert-unified-alert.$(OBJEXT) alert-unified2-alert.$(OBJEXT) \ ! alert-pgsql-log.$(OBJEXT) log-httplog.$(OBJEXT) \ ! stream.$(OBJEXT) stream-tcp.$(OBJEXT) \ stream-tcp-reassemble.$(OBJEXT) respond-reject.$(OBJEXT) \ respond-reject-libnet11.$(OBJEXT) conf.$(OBJEXT) \ conf-yaml-loader.$(OBJEXT) counters.$(OBJEXT) \ *************** *** 445,450 **** --- 446,452 ---- alert-unified-log.c alert-unified-log.h \ alert-unified-alert.c alert-unified-alert.h \ alert-unified2-alert.c alert-unified2-alert.h \ + alert-pgsql-log.c alert-pgsql-log.h \ log-httplog.c log-httplog.h \ stream.c stream.h \ stream-tcp.c stream-tcp.h stream-tcp-private.h \ *************** *** 489,497 **** exit 1;; \ esac; \ done; \ ! echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ ! $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ --- 491,499 ---- exit 1;; \ esac; \ done; \ ! echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ ! $(AUTOMAKE) --foreign src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *************** *** 565,570 **** --- 567,573 ---- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-debuglog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-fastlog.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-pgsql-log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-prelude.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-unified-alert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-unified-log.Po@am__quote@ diff -crN 1/src/output.c 2/src/output.c *** 1/src/output.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/output.c 2010-03-11 14:45:50.756231037 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2009 Open Information Security Foundation */ /** *************** *** 24,37 **** * * \retval Returns 0 on success, -1 on failure. */ ! void ! OutputRegisterModule(char *name, char *conf_name, LogFileCtx *(*InitFunc)(ConfNode *)) { ! OutputModule *module = calloc(1, sizeof(*module)); ! if (module == NULL) { ! SCLogError(SC_ERR_MEM_ALLOC, ! "Failed to allocated memory for new output module"); ! exit(EXIT_FAILURE); } module->name = strdup(name); --- 25,36 ---- * * \retval Returns 0 on success, -1 on failure. */ ! void OutputRegisterModule(char *name, char *conf_name, LogCtx *(*InitFunc)(ConfNode *)) { ! OutputModule *module = calloc(1, sizeof(OutputModule)); ! if (!module) { ! SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocated memory for new output module"); ! return; } module->name = strdup(name); *************** *** 39,45 **** module->InitFunc = InitFunc; TAILQ_INSERT_TAIL(&output_modules, module, entries); ! SCLogInfo("Output module \"%s\" registered.", name); } /** --- 38,44 ---- module->InitFunc = InitFunc; TAILQ_INSERT_TAIL(&output_modules, module, entries); ! SCLogInfo("Output module \"%s\" registered", name); } /** *************** *** 48,55 **** * \retval The OutputModule with the given name or NULL if no output module * with the given name is registered. */ ! OutputModule * ! OutputGetModuleByConfName(char *conf_name) { OutputModule *module; --- 47,53 ---- * \retval The OutputModule with the given name or NULL if no output module * with the given name is registered. */ ! OutputModule *OutputGetModuleByConfName(char *conf_name) { OutputModule *module; *************** *** 64,71 **** /** * \brief Deregister all modules. Useful for a memory clean exit. */ ! void ! OutputDeregisterAll(void) { OutputModule *module; --- 62,68 ---- /** * \brief Deregister all modules. Useful for a memory clean exit. */ ! void OutputDeregisterAll(void) { OutputModule *module; diff -crN 1/src/output.h 2/src/output.h *** 1/src/output.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/output.h 2010-03-11 14:45:50.863210992 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2009 Open Information Security Foundation */ /** *************** *** 9,24 **** #define __OUTPUT_H__ #include "suricata.h" typedef struct OutputModule_ { char *name; char *conf_name; ! LogFileCtx *(*InitFunc)(ConfNode *); TAILQ_ENTRY(OutputModule_) entries; } OutputModule; ! void OutputRegisterModule(char *, char *, LogFileCtx *(*)(ConfNode *)); OutputModule *OutputGetModuleByConfName(char *name); void OutputDeregisterAll(void); --- 10,33 ---- #define __OUTPUT_H__ #include "suricata.h" + #include "tm-modules.h" + #include "conf.h" + + typedef enum OutputType_ { + OT_FILE, + OT_SYSLOG, + OT_DATABASE, + } OutputType; typedef struct OutputModule_ { char *name; char *conf_name; ! struct LogCtx_ *(*InitFunc)(ConfNode *); TAILQ_ENTRY(OutputModule_) entries; } OutputModule; ! void OutputRegisterModule(char *, char *, struct LogCtx_ *(*)(ConfNode *)); OutputModule *OutputGetModuleByConfName(char *name); void OutputDeregisterAll(void); diff -crN 1/src/runmodes.c 2/src/runmodes.c *** 1/src/runmodes.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/runmodes.c 2010-03-11 14:45:50.554210363 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2009 Open Information Security Foundation */ /** \file *************** *** 22,27 **** --- 23,29 ---- #include "alert-unified-alert.h" #include "alert-unified2-alert.h" #include "alert-debuglog.h" + #include "alert-pgsql-log.h" #include "log-httplog.h" *************** *** 32,41 **** */ typedef struct RunModeOutput_ { TmModule *tm_module; ! LogFileCtx *logfile_ctx; TAILQ_ENTRY(RunModeOutput_) entries; } RunModeOutput; TAILQ_HEAD(, RunModeOutput_) RunModeOutputs = TAILQ_HEAD_INITIALIZER(RunModeOutputs); --- 34,45 ---- */ typedef struct RunModeOutput_ { TmModule *tm_module; ! OutputType otype; ! LogCtx *l_ctx; TAILQ_ENTRY(RunModeOutput_) entries; } RunModeOutput; + TAILQ_HEAD(, RunModeOutput_) RunModeOutputs = TAILQ_HEAD_INITIALIZER(RunModeOutputs); *************** *** 47,56 **** /* Close any log files. */ RunModeOutput *output; while ((output = TAILQ_FIRST(&RunModeOutputs))) { ! SCLogDebug("Shutting down output %s.", output->tm_module->name); TAILQ_REMOVE(&RunModeOutputs, output, entries); ! if (output->logfile_ctx != NULL) ! LogFileFreeCtx(output->logfile_ctx); free(output); } } --- 51,60 ---- /* Close any log files. */ RunModeOutput *output; while ((output = TAILQ_FIRST(&RunModeOutputs))) { ! SCLogDebug("Shutting down output %s", output->tm_module->name); TAILQ_REMOVE(&RunModeOutputs, output, entries); ! if (output->l_ctx) ! LogFreeCtx(output->l_ctx); free(output); } } *************** *** 61,67 **** void RunModeInitializeOutputs(void) { ConfNode *outputs = ConfGetNode("outputs"); ! if (outputs == NULL) { /* No "outputs" section in the configuration. */ return; } --- 65,71 ---- void RunModeInitializeOutputs(void) { ConfNode *outputs = ConfGetNode("outputs"); ! if (!outputs) { /* No "outputs" section in the configuration. */ return; } *************** *** 71,114 **** const char *enabled; TAILQ_FOREACH(output, &outputs->head, next) { - OutputModule *module = OutputGetModuleByConfName(output->val); ! if (module == NULL) { ! SCLogWarning(SC_ERR_INVALID_ARGUMENT, ! "No output module named %s, ignoring", output->val); ! continue; } output_config = ConfNodeLookupChild(output, module->conf_name); ! if (output_config == NULL) { /* Shouldn't happen. */ ! SCLogError(SC_ERR_INVALID_ARGUMENT, ! "Failed to lookup configuration child node: fast"); ! exit(1); } enabled = ConfNodeLookupChildValue(output_config, "enabled"); ! if (enabled != NULL && strcasecmp(enabled, "yes") == 0) { ! LogFileCtx *logfile_ctx = module->InitFunc(output_config); ! if (logfile_ctx == NULL) { /* In most cases the init function will have logged the * error. Maybe we should exit on init errors? */ continue; } tm_module = TmModuleGetByName(module->name); ! if (tm_module == NULL) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, ! "TmModuleGetByName for %s failed", module->name); ! exit(EXIT_FAILURE); } RunModeOutput *runmode_output = calloc(1, sizeof(RunModeOutput)); ! if (runmode_output == NULL) { ! SCLogError(SC_ERR_MEM_ALLOC, ! "Failed to allocate memory for output."); ! exit(EXIT_FAILURE); } runmode_output->tm_module = tm_module; ! runmode_output->logfile_ctx = logfile_ctx; TAILQ_INSERT_TAIL(&RunModeOutputs, runmode_output, entries); } } --- 75,114 ---- const char *enabled; TAILQ_FOREACH(output, &outputs->head, next) { OutputModule *module = OutputGetModuleByConfName(output->val); ! if (!module) { ! SCLogWarning(SC_ERR_INVALID_ARGUMENT, "No output module named %s, ignoring", output->val); ! continue; // maybe we should exit? } output_config = ConfNodeLookupChild(output, module->conf_name); ! if (!output_config) { /* Shouldn't happen. */ ! SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to lookup configuration child node: %s", module->conf_name); ! continue; } enabled = ConfNodeLookupChildValue(output_config, "enabled"); ! if (enabled && strcasecmp(enabled, "yes") == 0) { ! LogCtx *l_ctx = module->InitFunc(output_config); ! if (!l_ctx) { /* In most cases the init function will have logged the * error. Maybe we should exit on init errors? */ continue; } + tm_module = TmModuleGetByName(module->name); ! if (!tm_module) { ! SCLogError(SC_ERR_INVALID_ARGUMENT, "TmModuleGetByName for %s failed", module->name); ! continue; // maybe we should exit? } RunModeOutput *runmode_output = calloc(1, sizeof(RunModeOutput)); ! if (!runmode_output) { ! SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for output"); ! return; // maybe we should exit? } runmode_output->tm_module = tm_module; ! runmode_output->l_ctx = l_ctx; TAILQ_INSERT_TAIL(&RunModeOutputs, runmode_output, entries); } } *************** *** 124,130 **** { RunModeOutput *output; TAILQ_FOREACH(output, &RunModeOutputs, entries) { ! TmVarSlotSetFuncAppend(tv, output->tm_module, output->logfile_ctx); } } --- 124,130 ---- { RunModeOutput *output; TAILQ_FOREACH(output, &RunModeOutputs, entries) { ! TmVarSlotSetFuncAppend(tv, output->tm_module, output->l_ctx); } } *************** *** 134,236 **** /* create the threads */ ThreadVars *tv_receivepcap = TmThreadCreatePacketHandler("ReceivePcap","packetpool","packetpool","pickup-queue","simple","1slot_noinout"); if (tv_receivepcap == NULL) { ! printf("ERROR: TmThreadsCreate failed\n"); exit(EXIT_FAILURE); } TmModule *tm_module = TmModuleGetByName("ReceivePcap"); if (tm_module == NULL) { ! printf("ERROR: TmModuleGetByName failed for ReceivePcap\n"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_receivepcap,tm_module,(void *)iface); if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) { ! printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } ThreadVars *tv_decode1 = TmThreadCreatePacketHandler("Decode1","pickup-queue","simple","decode-queue1","simple","1slot"); ! if (tv_decode1 == NULL) { ! printf("ERROR: TmThreadsCreate failed for Decode1\n"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("DecodePcap"); ! if (tm_module == NULL) { ! printf("ERROR: TmModuleGetByName DecodePcap failed\n"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_decode1,tm_module,NULL); if (TmThreadSpawn(tv_decode1) != TM_ECODE_OK) { ! printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } ThreadVars *tv_stream1 = TmThreadCreatePacketHandler("Stream1","decode-queue1","simple","stream-queue1","simple","1slot"); ! if (tv_stream1 == NULL) { ! printf("ERROR: TmThreadsCreate failed for Stream1\n"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("StreamTcp"); ! if (tm_module == NULL) { ! printf("ERROR: TmModuleGetByName StreamTcp failed\n"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_stream1,tm_module,NULL); if (TmThreadSpawn(tv_stream1) != TM_ECODE_OK) { ! printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } ThreadVars *tv_detect1 = TmThreadCreatePacketHandler("Detect1","stream-queue1","simple","verdict-queue","simple","1slot"); ! if (tv_detect1 == NULL) { ! printf("ERROR: TmThreadsCreate failed\n"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("Detect"); ! if (tm_module == NULL) { ! printf("ERROR: TmModuleGetByName Detect failed\n"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_detect1,tm_module,(void *)de_ctx); if (TmThreadSpawn(tv_detect1) != TM_ECODE_OK) { ! printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } ThreadVars *tv_detect2 = TmThreadCreatePacketHandler("Detect2","stream-queue1","simple","verdict-queue","simple","1slot"); ! if (tv_detect2 == NULL) { ! printf("ERROR: TmThreadsCreate failed\n"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("Detect"); ! if (tm_module == NULL) { ! printf("ERROR: TmModuleGetByName Detect failed\n"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_detect2,tm_module,(void *)de_ctx); if (TmThreadSpawn(tv_detect2) != TM_ECODE_OK) { ! printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } ThreadVars *tv_rreject = TmThreadCreatePacketHandler("RespondReject","verdict-queue","simple","alert-queue1","simple","1slot"); ! if (tv_rreject == NULL) { ! printf("ERROR: TmThreadsCreate failed\n"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("RespondReject"); ! if (tm_module == NULL) { ! printf("ERROR: TmModuleGetByName for RespondReject failed\n"); exit(EXIT_FAILURE); } ! Tm1SlotSetFunc(tv_rreject,tm_module,NULL); if (TmThreadSpawn(tv_rreject) != TM_ECODE_OK) { ! printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } --- 134,236 ---- /* create the threads */ ThreadVars *tv_receivepcap = TmThreadCreatePacketHandler("ReceivePcap","packetpool","packetpool","pickup-queue","simple","1slot_noinout"); if (tv_receivepcap == NULL) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } TmModule *tm_module = TmModuleGetByName("ReceivePcap"); if (tm_module == NULL) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmModuleGetByName failed for ReceivePcap"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_receivepcap,tm_module,(void *)iface); if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } ThreadVars *tv_decode1 = TmThreadCreatePacketHandler("Decode1","pickup-queue","simple","decode-queue1","simple","1slot"); ! if (!tv_decode1) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadsCreate failed for Decode1"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("DecodePcap"); ! if (!tm_module) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmModuleGetByName DecodePcap failed"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_decode1,tm_module,NULL); if (TmThreadSpawn(tv_decode1) != TM_ECODE_OK) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } ThreadVars *tv_stream1 = TmThreadCreatePacketHandler("Stream1","decode-queue1","simple","stream-queue1","simple","1slot"); ! if (!tv_stream1) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadsCreate failed for Stream1"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("StreamTcp"); ! if (!tm_module) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmModuleGetByName StreamTcp failed"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_stream1,tm_module,NULL); if (TmThreadSpawn(tv_stream1) != TM_ECODE_OK) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } ThreadVars *tv_detect1 = TmThreadCreatePacketHandler("Detect1","stream-queue1","simple","verdict-queue","simple","1slot"); ! if (!tv_detect1) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("Detect"); ! if (!tm_module) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmModuleGetByName Detect failed"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_detect1,tm_module,(void *)de_ctx); if (TmThreadSpawn(tv_detect1) != TM_ECODE_OK) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } ThreadVars *tv_detect2 = TmThreadCreatePacketHandler("Detect2","stream-queue1","simple","verdict-queue","simple","1slot"); ! if (!tv_detect2) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("Detect"); ! if (!tm_module) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmModuleGetByName Detect failed"); exit(EXIT_FAILURE); } Tm1SlotSetFunc(tv_detect2,tm_module,(void *)de_ctx); if (TmThreadSpawn(tv_detect2) != TM_ECODE_OK) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } ThreadVars *tv_rreject = TmThreadCreatePacketHandler("RespondReject","verdict-queue","simple","alert-queue1","simple","1slot"); ! if (!tv_rreject) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("RespondReject"); ! if (!tm_module) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmModuleGetByName for RespondReject failed"); exit(EXIT_FAILURE); } ! Tm1SlotSetFunc(tv_rreject, tm_module, NULL); if (TmThreadSpawn(tv_rreject) != TM_ECODE_OK) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } *************** *** 238,244 **** "alert-queue1", "simple", "packetpool", "packetpool", "varslot"); SetupOutputs(tv_outputs); if (TmThreadSpawn(tv_outputs) != TM_ECODE_OK) { ! printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } --- 238,244 ---- "alert-queue1", "simple", "packetpool", "packetpool", "varslot"); SetupOutputs(tv_outputs); if (TmThreadSpawn(tv_outputs) != TM_ECODE_OK) { ! SCLogError(SC_ERR_TM_THREADS_ERROR, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } diff -crN 1/src/runmodes.h 2/src/runmodes.h *** 1/src/runmodes.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/runmodes.h 2010-03-11 14:45:50.421225729 +0300 *************** *** 1,3 **** --- 1,5 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ + #ifndef __RUNMODES_H__ #define __RUNMODES_H__ *************** *** 27,30 **** void RunModeShutDown(void); #endif /* __RUNMODES_H__ */ - --- 29,31 ---- diff -crN 1/src/suricata.c 2/src/suricata.c *** 1/src/suricata.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/suricata.c 2010-03-11 14:45:50.660211970 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ #include "suricata-common.h" *************** *** 43,48 **** --- 44,50 ---- #include "alert-unified2-alert.h" #include "alert-debuglog.h" #include "alert-prelude.h" + #include "alert-pgsql-log.h" #include "log-httplog.h" *************** *** 660,665 **** --- 662,668 ---- TmModuleAlertUnifiedLogRegister(); TmModuleAlertUnifiedAlertRegister(); TmModuleUnified2AlertRegister(); + TmModuleAlertPGSQLLogRegister(); TmModuleStreamTcpRegister(); TmModuleLogHttpLogRegister(); TmModuleLogHttpLogIPv4Register(); diff -crN 1/src/tm-modules.c 2/src/tm-modules.c *** 1/src/tm-modules.c 2010-02-19 20:47:52.000000000 +0300 --- 2/src/tm-modules.c 2010-03-11 17:57:52.071766636 +0300 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ /* Copyright (c) 2008 Victor Julien */ #include "suricata-common.h" *************** *** 20,28 **** } } ! /** \brief get a tm module ptr by name ! * \param name name string ! * \retval ptr to the module or NULL */ TmModule *TmModuleGetByName(char *name) { TmModule *t; uint16_t i; --- 21,31 ---- } } ! /** ! * \brief Get TmModule pointer by name ! * \param name name string ! * \retval ptr to the module or NULL ! */ TmModule *TmModuleGetByName(char *name) { TmModule *t; uint16_t i; *************** *** 40,94 **** return NULL; } ! /** \brief LogFileNewCtx() Get a new LogFileCtx ! * \retval LogFileCtx * pointer if succesful, NULL if error ! * */ ! LogFileCtx *LogFileNewCtx() { ! LogFileCtx* lf_ctx; ! lf_ctx=(LogFileCtx*)malloc(sizeof(LogFileCtx)); ! if(lf_ctx == NULL) ! { ! printf("LogFileCtxNew: Couldn't malloc \n"); return NULL; } - memset(lf_ctx, 0, sizeof(LogFileCtx)); - /** Ensure that it is unlocked */ - SCMutexInit(&lf_ctx->fp_mutex,NULL); - SCMutexUnlock(&lf_ctx->fp_mutex); ! return lf_ctx; } ! /** \brief LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory) ! * \param motcx pointer to the OutputCtx ! * \retval int 1 if succesful, 0 if error ! * */ ! int LogFileFreeCtx(LogFileCtx *lf_ctx) { ! int ret=0; ! ! if(lf_ctx != NULL) ! { ! if (lf_ctx->fp != NULL) ! { ! SCMutexLock(&lf_ctx->fp_mutex); ! fclose(lf_ctx->fp); ! SCMutexUnlock(&lf_ctx->fp_mutex); } ! if (lf_ctx->prefix != NULL) ! free(lf_ctx->prefix); ! if(lf_ctx->filename != NULL) ! free(lf_ctx->filename); ! free(lf_ctx); ! ret=1; } ! return ret; } ! /** \brief register all unittests for the tm modules */ void TmModuleRegisterTests(void) { #ifdef UNITTESTS TmModule *t; --- 43,119 ---- return NULL; } ! /** ! * \brief LogNewCtx() Get a new LogCtx ! * \retval LogCtx pointer if succesful, NULL if error ! */ ! LogCtx *LogNewCtx(void) { ! LogCtx *l_ctx; ! l_ctx = (LogCtx *)malloc(sizeof(LogCtx)); ! if (!l_ctx) { ! SCLogError(SC_ERR_MEM_ALLOC, "LogNewCtx: Failed to allocate memory for new output context\n"); return NULL; } ! memset(l_ctx, 0, sizeof(LogCtx)); ! ! /** Ensure that file mutex is unlocked */ ! SCMutexInit(&l_ctx->file.fp_mutex, NULL); ! SCMutexUnlock(&l_ctx->file.fp_mutex); ! ! return l_ctx; } ! /** ! * \brief LogFreeCtx() Destroy a LogCtx (close the file and free memory) ! * \param motcx pointer to the OutputCtx ! * \retval int 1 if succesful, 0 if error ! */ ! int LogFreeCtx(LogCtx *l_ctx) { ! if (l_ctx) { ! switch (l_ctx->otype) { ! case OT_FILE: ! if (l_ctx->file.fp) { ! SCMutexLock(&l_ctx->file.fp_mutex); ! fclose(l_ctx->file.fp); ! SCMutexUnlock(&l_ctx->file.fp_mutex); ! } ! if (l_ctx->file.prefix) ! free(l_ctx->file.prefix); ! if(l_ctx->file.filename) ! free(l_ctx->file.filename); ! break; ! case OT_DATABASE: ! if (l_ctx->db.host) ! free(l_ctx->db.host); ! if (l_ctx->db.port) ! free(l_ctx->db.port); ! if (l_ctx->db.db_name) ! free(l_ctx->db.db_name); ! if (l_ctx->db.login) ! free(l_ctx->db.login); ! if (l_ctx->db.table) ! free(l_ctx->db.table); ! break; ! case OT_SYSLOG: ! SCLogDebug("LogFreeCtx: Syslog is currently non implemented"); ! break; } ! ! free(l_ctx); ! ! return 1; } ! return 0; } ! /** ! * \brief register all unittests for the tm modules ! */ void TmModuleRegisterTests(void) { #ifdef UNITTESTS TmModule *t; *************** *** 100,112 **** if (t->name == NULL) continue; ! if (t->RegisterTests == NULL) { ! SCLogDebug("threading module %s has no unittest " ! "registration function.", t->name); ! } else { t->RegisterTests(); - } } #endif /* UNITTESTS */ } - --- 125,134 ---- if (t->name == NULL) continue; ! if (t->RegisterTests == NULL) ! SCLogDebug("Threading module %s has no unittest registration function", t->name); ! else t->RegisterTests(); } #endif /* UNITTESTS */ } diff -crN 1/src/tm-modules.h 2/src/tm-modules.h *** 1/src/tm-modules.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/tm-modules.h 2010-03-11 16:39:43.656766287 +0300 *************** *** 1,7 **** --- 1,17 ---- + /* Copyright (c) 2010 Andrew A. Usenok */ + #ifndef __TM_MODULES_H__ #define __TM_MODULES_H__ + #include + #include + #include "threadvars.h" + #include "output.h" + + #ifdef __SC_PGSQL_SUPPORT__ + #include "libpq-fe.h" + #endif /*Error codes for the thread modules*/ typedef enum { *************** *** 46,51 **** --- 56,64 ---- TMM_LOGHTTPLOG, TMM_LOGHTTPLOG4, TMM_LOGHTTPLOG6, + #ifdef __SC_PGSQL_SUPPORT__ + TMM_ALERTPGSQLLOG, + #endif TMM_STREAMTCP, TMM_DECODEIPFW, TMM_VERDICTIPFW, *************** *** 58,94 **** TmModule tmm_modules[TMM_SIZE]; ! /** Global structure for Output Context */ ! typedef struct LogFileCtx_ { ! FILE *fp; ! /** It will be locked if the log/alert ! * record cannot be written to the file in one call */ ! SCMutex fp_mutex; ! ! /** The name of the file */ ! char *filename; ! ! /**< Used by some alert loggers like the unified ones that append ! * the date onto the end of files. */ ! char *prefix; ! ! /** Generic size_limit and size_current ! * They must be common to the threads accesing the same file */ ! uint32_t size_limit; /**< file size limit */ ! uint32_t size_current; /**< file current size */ ! /* Alerts on the module (not on the file) */ uint64_t alerts; ! /* flag to avoid multiple threads printing the same stats */ ! uint8_t flags; ! } LogFileCtx; ! /* flags for LogFileCtx */ #define LOGFILE_HEADER_WRITTEN 0x01 #define LOGFILE_ALERTS_PRINTED 0x02 ! LogFileCtx *LogFileNewCtx(); ! int LogFileFreeCtx(LogFileCtx *); TmModule *TmModuleGetByName(char *name); TmEcode TmModuleRegister(char *name, int (*module_func)(ThreadVars *, Packet *, void *)); --- 71,138 ---- TmModule tmm_modules[TMM_SIZE]; ! /** Global structure for output context */ ! typedef struct LogCtx_ { ! OutputType otype; ! ! struct { ! FILE *fp; ! /** It will be locked if the log/alert ! * record cannot be written to the file in one call */ ! SCMutex fp_mutex; ! ! /** The name of the file */ ! char *filename; ! ! /**< Used by some alert loggers like the unified ones that append ! * the date onto the end of files. */ ! char *prefix; ! ! /** Generic size_limit and size_current ! * They must be common to the threads accesing the same file */ ! uint32_t size_limit; /**< file size limit */ ! uint32_t size_current; /**< file current size */ ! ! /** flag to avoid multiple threads printing the same stats */ ! uint8_t flags; ! } file; ! ! struct { ! /** Database specific fields */ ! union { ! #ifdef __SC_PGSQL_SUPPORT__ ! PGconn *pgconn; ! #endif ! }; ! ! /** Database server hostname ! * (if NULL, using local socket) */ ! char *host; ! ! /** Port number at server host */ ! char *port; ! ! /** The database name */ ! char *db_name; ! /** User name to connect as ! * (if NULL, no authentication demanded) */ ! char *login; ! ! /** The table name */ ! char *table; ! } db; ! ! /** Alerts on the module */ uint64_t alerts; ! } LogCtx; ! /* flags for file in LogCtx */ #define LOGFILE_HEADER_WRITTEN 0x01 #define LOGFILE_ALERTS_PRINTED 0x02 ! LogCtx *LogNewCtx(void); ! int LogFreeCtx(LogCtx *); TmModule *TmModuleGetByName(char *name); TmEcode TmModuleRegister(char *name, int (*module_func)(ThreadVars *, Packet *, void *)); *************** *** 96,99 **** void TmModuleRegisterTests(void); #endif /* __TM_MODULES_H__ */ - --- 140,142 ---- diff -crN 1/src/util-error.h 2/src/util-error.h *** 1/src/util-error.h 2010-02-19 20:47:52.000000000 +0300 --- 2/src/util-error.h 2010-03-11 14:45:50.624225729 +0300 *************** *** 1,4 **** ! /** Copyright (c) 2009 Open Information Security Foundation. * \author Anoop Saldanha * * \todo Needs refining of the error codes. Renaming with a prefix of SC_ERR, --- 1,5 ---- ! /* Copyright (c) 2010 Andrew A. Usenok ! * Copyright (c) 2009 Open Information Security Foundation. * \author Anoop Saldanha * * \todo Needs refining of the error codes. Renaming with a prefix of SC_ERR, *************** *** 94,99 **** --- 95,101 ---- SC_ERR_HTTP_LOG_GENERIC, SC_ERR_UNIFIED_ALERT_GENERIC, SC_ERR_UNIFIED2_ALERT_GENERIC, + SC_ERR_PGSQL_LOG_GENERIC, SC_ERR_FWRITE, SC_ERR_THRESHOLD_HASH_ADD, SC_ERR_UNDEFINED_VAR, diff -crN 1/suricata.yaml 2/suricata.yaml *** 1/suricata.yaml 2010-02-19 20:47:52.000000000 +0300 --- 2/suricata.yaml 2010-03-11 14:45:50.259211271 +0300 *************** *** 38,43 **** --- 38,53 ---- # Limit in MB. #limit: 32 + - pgsql: + enabled: yes + # Default is local socket + #host: pg_hostname + #port: 5432 + #dbname: sc_database + #login: sc_login + #password: sc_password + #table: sc_events + - http-log: enabled: yes filename: http.log