diff --git a/BuildOptions.cmake b/BuildOptions.cmake new file mode 100644 index 0000000000..cd1ac60d92 --- /dev/null +++ b/BuildOptions.cmake @@ -0,0 +1,50 @@ +#--------------------------------------------------------------------# +# # +# Bro - Build Setup # +# # +#--------------------------------------------------------------------# + +# The installation directory +set(CMAKE_INSTALL_PREFIX /usr/local + CACHE STRING "Installation directory" FORCE) + +# The installation subdirectory for Bro policy files +set(DATADIR share/bro + CACHE STRING "Installation subdirectory for Bro policy files" FORCE) + +# Enable active mapping processing +set(ACTIVE_MAPPING false + CACHE STRING "enable active mapping processing" FORCE) + +# Enable IPv6 processing +set(BROv6 false + CACHE STRING "enable IPv6 processing" FORCE) + +# Enable DFA state expiration +set(EXPIRE_DFA_STATES false + CACHE STRING "enable DFA state expiration" FORCE) + +# Enable select-based mainloop +set(USE_SELECT_LOOP false + CACHE STRING "enable select-based main loop" FORCE) + +# Enable non-blocking DNS support +set(USE_NB_DNS false + CACHE STRING "enable non-blocking DNS support" FORCE) + +# Enable use of int64 (long long) for integers +set(USE_INT64 false + CACHE STRING "enable use of int64 (long long) for integers" FORCE) + +# Uncomment to specify a custom prefix that contains the libpcap installation. +#set(PCAP_ROOT path/to/your/pcap) + +# Uncomment to specify a custom directory that contains libpcap headers. +#set(PCAP_INCLUDEDIR path/to/your/pcap/include) + +# Uncomment to specify a custom directory that contains the libpcap library. +#set(PCAP_LIBRARYDIR path/to/your/pcap/lib) + +# Attempt to use non-blocking DNS support by default +set(USE_NB_DNS true + CACHE BOOL "Use non-blocking DNS support" FORCE) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..65a34e7e55 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,91 @@ +## +## CMake Configuration +## + +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) + +# Prohibit in-source builds. +string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" source_build) +if (source_build) + message(FATAL_ERROR "In-source builds are not allowed\n." + "Please create a separate build directory and invoke cmake from there.") +endif () + +# If the build configuration file does not exist, copy it over. +set(build_config BuildOptions.cmake) +find_file(build_config_file + NAMES BuildOptions.cmake + PATHS ${CMAKE_BINARY_DIR} + DOC "Build configuration" + NO_DEFAULT_PATH + ) +if (NOT build_config_file) + message("No build configuration found, using default.") + configure_file(${CMAKE_SOURCE_DIR}/${build_config} + ${CMAKE_BINARY_DIR}/${build_config} + ) +endif () +mark_as_advanced(build_config_file) + +include(${CMAKE_BINARY_DIR}/${build_config}) + +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/) + +## +## Project Configuration +## + +project(Bro) + +set(PACKAGE "Bro") +file(STRINGS "${CMAKE_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1) + +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) +find_package(PCAP REQUIRED) +include_directories(BEFORE ${PCAP_INCLUDE_DIR}) + +# TODO: find libpcap from system or use shipped version +# TODO: find bind8 lib? +# TODO: optional OpenSSL +# TODO: optional libmagic +# TODO: optional libGeoIP +# TODO: optional libz +# TODO: optional Endace's DAG tools +# TODO: optional Google perftools +# TODO: what's the equivalent of these configure settings: +# TODO: compiler warning flags +# --disable-dependency-tracking speeds up one-time build +# --enable-dependency-tracking do not reject slow dependency extractors +# --disable-largefile omit support for large files + +include(TestBigEndian) +test_big_endian(WORDS_BIGENDIAN) + +include(OSSpecific) +include(CheckTypes) +include(CheckHeaders) +include(CheckFunctions) +include(MiscTests) +include(PCAPTests) +#TODO: use/integrate find_package(OpenSSL) +include(OpenSSLTests) + +#TODO: NB_DNS tests +set(HAVE_NB_DNS ${USE_NB_DNS}) +set(HAVE_ASYNC_DNS ${USE_NB_DNS}) #TODO: should make consistent w/ HAVE_NB_DNS + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) + +add_definitions(-DHAVE_CONFIG_H) + +add_subdirectory(binpac) +add_subdirectory(src) +#add_subdirectory(aux) +#add_subdirectory(scripts) +#add_subdirectory(policy) +#add_subdirectory(doc) diff --git a/cmake/modules/CheckFunctions.cmake b/cmake/modules/CheckFunctions.cmake new file mode 100644 index 0000000000..208c534455 --- /dev/null +++ b/cmake/modules/CheckFunctions.cmake @@ -0,0 +1,17 @@ +include(CheckFunctionExists) + +check_function_exists(getopt_long HAVE_GETOPT_LONG) +check_function_exists(mallinfo HAVE_MALLINFO) +check_function_exists(pfopen HAVE_PFOPEN) +check_function_exists(strcasestr HAVE_STRCASESTR) +check_function_exists(strerror HAVE_STRERROR) +check_function_exists(strftime HAVE_STRFTIME) +check_function_exists(strsep HAVE_STRSEP) +check_function_exists(sigset HAVE_SIGSET) + +if(HAVE_SIGSET) + set(SIG_FUNC sigset) +else() + set(SIG_FUNC signal) + check_function_exists(sigaction HAVE_SIGACTION) +endif() diff --git a/cmake/modules/CheckHeaders.cmake b/cmake/modules/CheckHeaders.cmake new file mode 100644 index 0000000000..2bdcb3dba3 --- /dev/null +++ b/cmake/modules/CheckHeaders.cmake @@ -0,0 +1,41 @@ +include(CheckIncludeFiles) +include(CheckStructHasMember) + +check_include_files(GeoIPCity.h HAVE_GEOIPCITY_H) +check_include_files(getopt.h HAVE_GETOPT_H) +check_include_files(inttypes.h HAVE_INTTYPES_H) +check_include_files(magic.h HAVE_MAGIC_H) +check_include_files(memory.h HAVE_MEMORY_H) +check_include_files(netinet/ether.h HAVE_NETINET_ETHER_H) +check_include_files(netinet/if_ether.h HAVE_NETINET_IF_ETHER_H) +check_include_files(netinet/in.h HAVE_NETINET_IN_H) +check_include_files(netinet/ip6.h HAVE_NETINET_IP6_H) +check_include_files(net/ethernet.h HAVE_NET_ETHERNET_H) +check_include_files(socket.h HAVE_SOCKET_H) +check_include_files(stdint.h HAVE_STDINT_H) +check_include_files(stdlib.h HAVE_STDLIB_H) +check_include_files(strings.h HAVE_STRINGS_H) +check_include_files(string.h HAVE_STRING_H) +check_include_files(sys/ethernet.h HAVE_SYS_ETHERNET_H) +check_include_files(sys/stat.h HAVE_SYS_STAT_H) +check_include_files(sys/types.h HAVE_SYS_TYPES_H) +check_include_files(termcap.h HAVE_TERMCAP_H) +check_include_files(term.h HAVE_TERM_H) +check_include_files(unistd.h HAVE_UNISTD_H) +check_include_files(time.h HAVE_TIME_H) +check_include_files(sys/time.h HAVE_SYS_TIME_H) +check_include_files("time.h;sys/time.h" TIME_WITH_SYS_TIME) +check_include_files(os-proto.h HAVE_OS_PROTO_H) + +check_struct_has_member(HISTORY_STATE entries "stdio.h;readline/readline.h" + HAVE_READLINE_HISTORY_ENTRIES) +check_include_files("stdio.h;readline/readline.h" HAVE_READLINE_READLINE_H) +check_include_files("stdio.h;readline/history.h" HAVE_READLINE_HISTORY_H) + +if (HAVE_READLINE_READLINE_H AND + HAVE_READLINE_HISTORY_H AND + HAVE_READLINE_HISTORY_ENTRIES) + set(HAVE_READLINE true) +endif () + +check_struct_has_member("struct sockaddr_in" sin_len "netinet/in.h" SIN_LEN) diff --git a/cmake/modules/CheckTypes.cmake b/cmake/modules/CheckTypes.cmake new file mode 100644 index 0000000000..5bbd6ab996 --- /dev/null +++ b/cmake/modules/CheckTypes.cmake @@ -0,0 +1,51 @@ +include(CheckTypeSize) + +check_type_size("long int" SIZEOF_LONG_INT) +check_type_size("long long" SIZEOF_LONG_LONG) +check_type_size("void *" SIZEOF_VOID_P) + +set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h) + +check_type_size(int32_t INT32_T) +if (INT32_T) + set(INT32_T int32_t) +else() + set(INT32_T int) +endif() + +check_type_size(u_int32_t U_INT32_T) +if (U_INT32_T) + set(U_INT32_T u_int32_t) +else () + set(INT32_T u_int) +endif () + +check_type_size(u_int16_t U_INT16_T) +if (U_INT16_T) + set(U_INT16_T u_int16_t) +else () + set(INT16_T u_short) +endif () + +check_type_size(u_int8_t U_INT8_T) +if (U_INT8_T) + set(U_INT8_T u_int8_t) +else () + set(INT8_T u_char) +endif () + +unset(CMAKE_EXTRA_INCLUDE_FILES) + +set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) +check_type_size(socklen_t SOCKLEN_T) +if (SOCKLEN_T) + set(SOCKLEN_T socklen_t) +else () + set(SOCKLEN_T int) +endif () +unset(CMAKE_EXTRA_INCLUDE_FILES) + +set(CMAKE_EXTRA_INCLUDE_FILES sys/sem.h) +check_type_size("struct sembuf" STRUCT_SEMBUF) +check_type_size("union semun" UNION_SEMUN) +unset(CMAKE_EXTRA_INCLUDE_FILES) diff --git a/cmake/modules/FindBISON.cmake b/cmake/modules/FindBISON.cmake new file mode 100644 index 0000000000..4d9e0e1a91 --- /dev/null +++ b/cmake/modules/FindBISON.cmake @@ -0,0 +1,220 @@ +# - Find bison executable and provides macros to generate custom build rules +# The module defines the following variables: +# +# BISON_EXECUTABLE - path to the bison program +# BISON_VERSION - version of bison +# BISON_FOUND - true if the program was found +# +# If bison is found, the module defines the macros: +# BISON_TARGET( [VERBOSE ] +# [COMPILE_FLAGS ] [HEADER ]) +# which will create a custom rule to generate a parser. is +# the path to a yacc file. is the name of the source file +# generated by bison. A header file containing the token list is also +# generated according to bison's -d option by default or if the HEADER +# option is used, the argument is passed to bison's --defines option to +# specify output file. If COMPILE_FLAGS option is specified, the next +# parameter is added in the bison command line. if VERBOSE option is +# specified, is created and contains verbose descriptions of the +# grammar and parser. The macro defines a set of variables: +# BISON_${Name}_DEFINED - true is the macro ran successfully +# BISON_${Name}_INPUT - The input source file, an alias for +# BISON_${Name}_OUTPUT_SOURCE - The source file generated by bison +# BISON_${Name}_OUTPUT_HEADER - The header file generated by bison +# BISON_${Name}_OUTPUTS - The sources files generated by bison +# BISON_${Name}_COMPILE_FLAGS - Options used in the bison command line +# +# ==================================================================== +# Example: +# +# find_package(BISON) +# BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp) +# add_executable(Foo main.cpp ${BISON_MyParser_OUTPUTS}) +# ==================================================================== + +#============================================================================= +# Copyright 2009 Kitware, Inc. +# Copyright 2006 Tristan Carel +# Modified 2010 by Jon Siwek, adding HEADER option +# +# Distributed under the OSI-approved BSD License (the "License"): +# CMake - Cross Platform Makefile Generator +# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +FIND_PROGRAM(BISON_EXECUTABLE bison DOC "path to the bison executable") +MARK_AS_ADVANCED(BISON_EXECUTABLE) + +IF(BISON_EXECUTABLE) + + EXECUTE_PROCESS(COMMAND ${BISON_EXECUTABLE} --version + OUTPUT_VARIABLE BISON_version_output + ERROR_VARIABLE BISON_version_error + RESULT_VARIABLE BISON_version_result + OUTPUT_STRIP_TRAILING_WHITESPACE) + IF(NOT ${BISON_version_result} EQUAL 0) + MESSAGE(SEND_ERROR "Command \"${BISON_EXECUTABLE} --version\" failed with output:\n${BISON_version_error}") + ELSE() + STRING(REGEX REPLACE "^bison \\(GNU Bison\\) ([^\n]+)\n.*" "\\1" + BISON_VERSION "${BISON_version_output}") + ENDIF() + + # internal macro + MACRO(BISON_TARGET_option_verbose Name BisonOutput filename) + LIST(APPEND BISON_TARGET_cmdopt "--verbose") + GET_FILENAME_COMPONENT(BISON_TARGET_output_path "${BisonOutput}" PATH) + GET_FILENAME_COMPONENT(BISON_TARGET_output_name "${BisonOutput}" NAME_WE) + ADD_CUSTOM_COMMAND(OUTPUT ${filename} + COMMAND ${CMAKE_COMMAND} + ARGS -E copy + "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output" + "${filename}" + DEPENDS + "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output" + COMMENT "[BISON][${Name}] Copying bison verbose table to ${filename}" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + SET(BISON_${Name}_VERBOSE_FILE ${filename}) + LIST(APPEND BISON_TARGET_extraoutputs + "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output") + ENDMACRO(BISON_TARGET_option_verbose) + + # internal macro + MACRO(BISON_TARGET_option_extraopts Options) + SET(BISON_TARGET_extraopts "${Options}") + SEPARATE_ARGUMENTS(BISON_TARGET_extraopts) + LIST(APPEND BISON_TARGET_cmdopt ${BISON_TARGET_extraopts}) + ENDMACRO(BISON_TARGET_option_extraopts) + + #============================================================ + # BISON_TARGET (public macro) + #============================================================ + # + MACRO(BISON_TARGET Name BisonInput BisonOutput) + SET(BISON_TARGET_output_header "") + SET(BISON_TARGET_command_opt "") + SET(BISON_TARGET_outputs "${BisonOutput}") + IF(NOT ${ARGC} EQUAL 3 AND + NOT ${ARGC} EQUAL 5 AND + NOT ${ARGC} EQUAL 7 AND + NOT ${ARGC} EQUAL 9) + MESSAGE(SEND_ERROR "Usage") + ELSE() + # Parsing parameters + IF(${ARGC} GREATER 5 OR ${ARGC} EQUAL 5) + IF("${ARGV3}" STREQUAL "VERBOSE") + BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV4}") + ENDIF() + IF("${ARGV3}" STREQUAL "COMPILE_FLAGS") + BISON_TARGET_option_extraopts("${ARGV4}") + ENDIF() + IF("${ARGV3}" STREQUAL "HEADER") + set(BISON_TARGET_output_header "${ARGV4}") + ENDIF() + ENDIF() + + IF(${ARGC} GREATER 7 OR ${ARGC} EQUAL 7) + IF("${ARGV5}" STREQUAL "VERBOSE") + BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV6}") + ENDIF() + + IF("${ARGV5}" STREQUAL "COMPILE_FLAGS") + BISON_TARGET_option_extraopts("${ARGV6}") + ENDIF() + + IF("${ARGV5}" STREQUAL "HEADER") + set(BISON_TARGET_output_header "${ARGV6}") + ENDIF() + ENDIF() + + IF(${ARGC} EQUAL 9) + IF("${ARGV7}" STREQUAL "VERBOSE") + BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV8}") + ENDIF() + + IF("${ARGV7}" STREQUAL "COMPILE_FLAGS") + BISON_TARGET_option_extraopts("${ARGV8}") + ENDIF() + + IF("${ARGV7}" STREQUAL "HEADER") + set(BISON_TARGET_output_header "${ARGV8}") + ENDIF() + ENDIF() + + IF(BISON_TARGET_output_header) + # Header's name passed in as argument to be used in --defines option + LIST(APPEND BISON_TARGET_cmdopt + "--defines=${BISON_TARGET_output_header}") + set(BISON_${Name}_OUTPUT_HEADER ${BISON_TARGET_output_header}) + ELSE() + # Header's name generated by bison (see option -d) + LIST(APPEND BISON_TARGET_cmdopt "-d") + STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${ARGV2}") + STRING(REPLACE "c" "h" _fileext ${_fileext}) + STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}" + BISON_${Name}_OUTPUT_HEADER "${ARGV2}") + ENDIF() + + LIST(APPEND BISON_TARGET_outputs "${BISON_${Name}_OUTPUT_HEADER}") + + ADD_CUSTOM_COMMAND(OUTPUT ${BISON_TARGET_outputs} + ${BISON_TARGET_extraoutputs} + COMMAND ${BISON_EXECUTABLE} + ARGS ${BISON_TARGET_cmdopt} -o ${ARGV2} ${ARGV1} + DEPENDS ${ARGV1} + COMMENT "[BISON][${Name}] Building parser with bison ${BISON_VERSION}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + + # define target variables + SET(BISON_${Name}_DEFINED TRUE) + SET(BISON_${Name}_INPUT ${ARGV1}) + SET(BISON_${Name}_OUTPUTS ${BISON_TARGET_outputs}) + SET(BISON_${Name}_COMPILE_FLAGS ${BISON_TARGET_cmdopt}) + SET(BISON_${Name}_OUTPUT_SOURCE "${BisonOutput}") + + ENDIF(NOT ${ARGC} EQUAL 3 AND + NOT ${ARGC} EQUAL 5 AND + NOT ${ARGC} EQUAL 7 AND + NOT ${ARGC} EQUAL 9) + ENDMACRO(BISON_TARGET) + # + #============================================================ + +ENDIF(BISON_EXECUTABLE) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON DEFAULT_MSG BISON_EXECUTABLE) + +# FindBISON.cmake ends here diff --git a/cmake/modules/FindPCAP.cmake b/cmake/modules/FindPCAP.cmake new file mode 100644 index 0000000000..d309b1ead9 --- /dev/null +++ b/cmake/modules/FindPCAP.cmake @@ -0,0 +1,73 @@ +# - Try to find libpcap include dirs and libraries +# +# Usage of this module as follows: +# +# find_package(PCAP) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# PCAP_ROOT Preferred installation prefix for searching for +# libpcap, set this if the module has problems +# finding the proper installation path. +# PCAP_INCLUDEDIR Set this to the include directory of libpcap if +# the module has problems finding the installation +# path. +# PCAP_LIBRARYDIR Set this to the library directory of libpcap if +# the module has problems finding the installation +# path. +# +# Variables defined by this module: +# +# PCAP_FOUND System has libpcap, include and library dirs found +# PCAP_INCLUDE_DIR The libpcap include directories. +# PCAP_LIBRARY The libpcap library. + +if (PCAP_ROOT) + message(STATUS "Searching for libpcap rooted in: ${PCAP_ROOT}") + set(PCAP_ADDITIONAL_INCLUDE_SEARCH_DIRS ${PCAP_ROOT}/include) + set(PCAP_ADDITIONAL_LIBRARY_SEARCH_DIRS ${PCAP_ROOT}/lib) +endif () + +if (PCAP_INCLUDEDIR) + message(STATUS "Searching for libpcap headers in: ${PCAP_INCLUDEDIR}") + set(PCAP_ADDITIONAL_INCLUDE_SEARCH_DIRS ${PCAP_INCLUDEDIR}) +endif () + +if (PCAP_LIBRARYDIR) + message(STATUS "Searching for libpcap libraries in: ${PCAP_LIBRARYDIR}") + set(PCAP_ADDITIONAL_LIBRARY_SEARCH_DIRS ${PCAP_LIBRARYDIR}) +endif () + +find_path(PCAP_INCLUDE_DIR + NAMES + pcap.h + PATHS + ${PCAP_ADDITIONAL_INCLUDE_SEARCH_DIRS} +) + +find_library(PCAP_LIBRARY + NAMES + pcap + PATHS + ${PCAP_ADDITIONAL_LIBRARY_SEARCH_DIRS} +) + +if (PCAP_INCLUDE_DIR AND PCAP_LIBRARY) + set(PCAP_FOUND true) +endif () + +if (PCAP_FOUND) + if (NOT PCAP_FIND_QUIETLY) + message(STATUS "Found libpcap") + endif () +else () + if (PCAP_FIND_REQUIRED) + message(FATAL_ERROR "Could not find required libpcap") + endif () +endif () + +mark_as_advanced( + PCAP_INCLUDE_DIR + PCAP_LIBRARY +) diff --git a/cmake/modules/MiscTests.cmake b/cmake/modules/MiscTests.cmake new file mode 100644 index 0000000000..da46dd83d7 --- /dev/null +++ b/cmake/modules/MiscTests.cmake @@ -0,0 +1,34 @@ +include(CheckCXXSourceCompiles) +include(CheckCSourceCompiles) + +# This autoconf variable is obsolete; it's portable to assume C89 and signal +# handlers returning void +set(RETSIGTYPE "void") +set(RETSIGVAL "") + +check_c_source_compiles(" + #include + #include + extern int socket(int, int, int); + extern int connect(int, const struct sockaddr *, int); + extern int send(int, const void *, int, int); + extern int recvfrom(int, void *, int, int, struct sockaddr *, int *); + int main() { return 0; } +" DO_SOCK_DECL) +if (DO_SOCK_DECL) + message(STATUS "socket() and friends need explicit declaration") +endif () + +check_cxx_source_compiles(" + #include + #include + extern \"C\" { + int openlog(const char* ident, int logopt, int facility); + int syslog(int priority, const char* message_fmt, ...); + int closelog(); + } + int main() { return 0; } +" SYSLOG_INT) +if (SYSLOG_INT) + message(STATUS "syslog prototypes need declaration") +endif () diff --git a/cmake/modules/OSSpecific.cmake b/cmake/modules/OSSpecific.cmake new file mode 100644 index 0000000000..fc91c20bcf --- /dev/null +++ b/cmake/modules/OSSpecific.cmake @@ -0,0 +1,90 @@ +if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + set(USE_NMALLOC true) + +elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") + set(HAVE_OPENBSD true) + set(USE_NMALLOC true) + +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + if (USE_NB_DNS) + include(CheckCSourceCompiles) + check_c_source_compiles(" +#include + int main() { + HEADER *hdr; int d = NS_IN6ADDRSZ; return 0; + } + " ns_header_defined) + if (NOT ns_header_defined) + check_c_source_compiles(" +#include +#include + int main() { + HEADER *hdr; int d = NS_IN6ADDRSZ; return 0; + } + " NEED_NAMESER_COMPAT_H) + if (NOT NEED_NAMESER_COMPAT_H) + message(WARNING "Darwin nameser compatibility check failed." + "Non-blocking DNS support disabled.") + set(USE_NB_DNS false) + endif () + endif () + endif () + +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(HAVE_LINUX true) + # TODO: configure.in sets -I/${top_srcdir}/linux-include; necessary? + #include_directories(${CMAKE_SOURCE_DIR}/linux-include) + +elseif (${CMAKE_SYSTEM_NAME} MATCHES "Solaris") + set(SOCKET_LIBS nsl socket) + +elseif (${CMAKE_SYSTEM_NAME} MATCHES "osf") + # Workaround ip_hl vs. ip_vhl problem in netinet/ip.h + add_definitions(-D__STDC__=2) + +elseif (${CMAKE_SYSTEM_NAME} MATCHES "irix") + list(APPEND CMAKE_C_FLAGS -xansi -signed -g3) + list(APPEND CMAKE_CXX_FLAGS -xansi -signed -g3) + +elseif (${CMAKE_SYSTEM_NAME} MATCHES "ultrix") + list(APPEND CMAKE_C_FLAGS -std1 -g3) + list(APPEND CMAKE_CXX_FLAGS -std1 -g3) + include(CheckCSourceCompiles) + check_c_source_compiles(" +#include + int main() { + void c(const struct a *); + return 0; + } + " have_ultrix_const) + if (NOT have_ultrix_const) + set(NEED_ULTRIX_CONST_HACK true) + endif () + +elseif (${CMAKE_SYSTEM_NAME} MATCHES "hpux" OR + ${CMAKE_SYSTEM_NAME} MATCHES "HP-UX") + include(CheckCSourceCompiles) + set(CMAKE_REQUIRED_FLAGS -Aa) + set(CMAKE_REQUIRED_DEFINITIONS -D_HPUX_SOURCE) + check_c_source_compiles(" +#include + int main() { + int frob(int, char *); + return 0; + } + " have_ansi_prototypes) + unset(CMAKE_REQUIRED_FLAGS) + unset(CMAKE_REQUIRED_DEFINITIONS) + + if (have_ansi_prototypes) + add_definitions(-D_HPUX_SOURCE) + list(APPEND CMAKE_C_FLAGS -Aa) + list(APPEND CMAKE_CXX_FLAGS -Aa) + endif () + + if (NOT have_ansi_prototypes) + message(FATAL_ERROR "Can't get HPUX compiler to handle ANSI prototypes") + endif () +endif () + + diff --git a/cmake/modules/OpenSSLTests.cmake b/cmake/modules/OpenSSLTests.cmake new file mode 100644 index 0000000000..b588cc311e --- /dev/null +++ b/cmake/modules/OpenSSLTests.cmake @@ -0,0 +1,56 @@ +if (USE_OPENSSL) + check_c_source_compiles(" + #include + int main() { return 0; } + " including_ssl_h_works) + + if (NOT including_ssl_h_works) + # On Red Hat we may need to include Kerberos header. + set(CMAKE_REQUIRED_INCLUDES "/usr/kerberos/include") + check_c_source_compiles(" + #include + #include + int main() { return 0; } + " NEED_KRB5_H) + unset(CMAKE_REQUIRED_INCLUDES) + if (NOT NEED_KRB5_H) + message(WARNING "Can't compile OpenSSL test; disabling OpenSSL") + set(USE_OPENSSL false) + else () + message(STATUS "OpenSSL requires Kerberos header") + include_directories("/usr/kerberos/include") + endif () + endif () +endif() + +if (USE_OPENSSL) + # check for OPENSSL_add_all_algorithms_conf function + # and thus OpenSSL >= v0.9.7 + set(CMAKE_REQUIRED_LIBRARIES crypto ssl) + check_c_source_compiles(" + #include + int main() { + OPENSSL_add_all_algorithms_conf(); + return 0; + } + " USE_OPENSSL) + unset(CMAKE_REQUIRED_LIBRARIES) + if (NOT USE_OPENSSL) + message(WARNING "OpenSSL >= v0.9.7 required; disabling OpenSSL") + endif () +endif () + +if (USE_OPENSSL) + set(CMAKE_REQUIRED_LIBRARIES crypto) + file(READ "${CONFTEST_DIR}/openssl_d2i_x509_const.c" CONFTEST) + check_cxx_source_compiles("${CONFTEST}" OPENSSL_D2I_X509_USES_CONST_CHAR) + if (NOT OPENSSL_D2I_X509_USES_CONST_CHAR) + file(READ "${CONFTEST_DIR}/openssl_d2i_x509.c" CONFTEST) + # double check + check_cxx_source_compiles("${CONFTEST}" OPENSSL_D2I_X509_USES_CHAR) + if (NOT OPENSSL_D2I_X509_USES_CHAR) + message(FATAL_ERROR "Can't determine if openssl_d2i_x509() takes a const char parameter") + endif (NOT OPENSSL_D2I_X509_USES_CHAR) + endif (NOT OPENSSL_D2I_X509_USES_CONST_CHAR) + unset(CMAKE_REQUIRED_LIBRARIES) +endif () diff --git a/cmake/modules/PCAPTests.cmake b/cmake/modules/PCAPTests.cmake new file mode 100644 index 0000000000..2c133dde0b --- /dev/null +++ b/cmake/modules/PCAPTests.cmake @@ -0,0 +1,72 @@ +include(CheckFunctionExists) +include(CheckCSourceCompiles) +include(CheckIncludeFiles) + +set(CMAKE_REQUIRED_INCLUDES ${LIBPCAP_INCLUDE_DIR}) +set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) + +check_include_files(pcap-int.h HAVE_PCAP_INT_H) + +check_function_exists(pcap_freecode HAVE_LIBPCAP_PCAP_FREECODE) +if (NOT HAVE_LIBPCAP_PCAP_FREECODE) + set(DONT_HAVE_LIBPCAP_PCAP_FREECODE true) + message(STATUS "No implementation for pcap_freecode()") +endif () + +check_c_source_compiles(" +#include +int main () { + int snaplen; + int linktype; + struct bpf_program fp; + int optimize; + bpf_u_int32 netmask; + char str[10]; + char error[1024]; + snaplen = 50; + linktype = DLT_EN10MB; + optimize = 1; + netmask = 0L; + str[0] = 'i'; str[1] = 'p'; str[2] = '\\\\0'; + (void)pcap_compile_nopcap( + snaplen, linktype, &fp, str, optimize, netmask, &error); + return 0; +} +" LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER) +if (NOT LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER) + # double check + check_c_source_compiles(" +#include +int main () { + int snaplen; + int linktype; + struct bpf_program fp; + int optimize; + bpf_u_int32 netmask; + char str[10]; + snaplen = 50; + linktype = DLT_EN10MB; + optimize = 1; + netmask = 0L; + str[0] = 'i'; str[1] = 'p'; str[2] = '\\\\0'; + (void)pcap_compile_nopcap(snaplen, linktype, &fp, str, optimize, netmask); + return 0; +} +" LIBPCAP_PCAP_COMPILE_NOPCAP_NO_ERROR_PARAMETER) + if (NOT LIBPCAP_PCAP_COMPILE_NOPCAP_NO_ERROR_PARAMETER) + message(FATAL_ERROR + "Can't determine if pcap_compile_nopcap takes an error parameter") + endif () +endif () + +check_c_source_compiles(" +#include +extern char pcap_version[]; +int main() { + puts(pcap_version); + return 0; +} +" PCAP_VERSION_STRING) + +unset(CMAKE_REQUIRED_INCLUDES) +unset(CMAKE_REQUIRED_LIBRARIES) diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000000..df9ea63df2 --- /dev/null +++ b/config.h.in @@ -0,0 +1,235 @@ +/* Enable active mapping processing */ +#cmakedefine ACTIVE_MAPPING + +/* enable IPV6 processing */ +#cmakedefine BROv6 + +/* Old libpcap versions (< 0.6.1) need defining pcap_freecode and + pcap_compile_nopcap */ +#cmakedefine DONT_HAVE_LIBPCAP_PCAP_FREECODE + +/* should explicitly declare socket() and friends */ +#cmakedefine DO_SOCK_DECL + +/* Enable DFA state expiration */ +#cmakedefine EXPIRE_DFA_STATES + +/* Define if you have the header file. */ +#cmakedefine HAVE_GEOIPCITY_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_GETOPT_H + +/* Define if you have the `getopt_long' function. */ +#cmakedefine HAVE_GETOPT_LONG + +/* Define if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H + +/* Define if you have the `magic' library (-lmagic). */ +#undef HAVE_LIBMAGIC + +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + +/* We are on a Linux system */ +#cmakedefine HAVE_LINUX + +/* Define if you have the header file. */ +#cmakedefine HAVE_MAGIC_H + +/* Define if you have the `mallinfo' function. */ +#cmakedefine HAVE_MALLINFO + +/* Define if you have the header file. */ +#cmakedefine HAVE_MEMORY_H + +/* async dns support */ +#cmakedefine HAVE_NB_DNS + +/* Define if you have the header file. */ +#cmakedefine HAVE_NETINET_ETHER_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_NETINET_IF_ETHER_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_NETINET_IP6_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_NET_ETHERNET_H + +/* We are on a OpenBSD system */ +#cmakedefine HAVE_OPENBSD + +/* have os-proto.h */ +#cmakedefine HAVE_OS_PROTO_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_PCAP_INT_H + +/* Define if you have the `pfopen' function. */ +#cmakedefine HAVE_PFOPEN + +/* line editing & history powers */ +#cmakedefine HAVE_READLINE + +/* Define if you have the `sigaction' function, but not `sigset'. */ +#cmakedefine HAVE_SIGACTION + +/* Define if you have the `sigset' function. */ +#cmakedefine HAVE_SIGSET + +/* Define if you have the header file. */ +#cmakedefine HAVE_SOCKET_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_STDINT_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_STDLIB_H + +/* Define if you have the `strcasestr' function. */ +#cmakedefine HAVE_STRCASESTR + +/* Define if you have the `strerror' function. */ +#cmakedefine HAVE_STRERROR + +/* Define if you have the `strftime' function. */ +#cmakedefine HAVE_STRFTIME + +/* Define if you have the header file. */ +#cmakedefine HAVE_STRINGS_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_STRING_H + +/* Define if you have the `strsep' function. */ +#cmakedefine HAVE_STRSEP + +/* Define if the system has the type `struct sembuf'. */ +#cmakedefine HAVE_STRUCT_SEMBUF + +/* Define if you have the header file. */ +#cmakedefine HAVE_SYS_ETHERNET_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_TERMCAP_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_TERM_H + +/* Define if the system has the type `union semun'. */ +#cmakedefine HAVE_UNION_SEMUN + +/* Define if you have the header file. */ +#cmakedefine HAVE_UNISTD_H + +/* Some libpcap versions use an extra parameter (error) in pcap_compile_nopcap + */ +#cmakedefine LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER + +/* Include krb5.h */ +#cmakedefine NEED_KRB5_H + +/* Compatibility for Darwin */ +#cmakedefine NEED_NAMESER_COMPAT_H + +/* d2i_x509 uses const char** */ +#cmakedefine OPENSSL_D2I_X509_USES_CONST_CHAR + +/* Name of package */ +#define PACKAGE "@PACKAGE@" + +/* Have a version string in libpcap */ +#cmakedefine PCAP_VERSION_STRING + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE @RETSIGTYPE@ + +/* signal function return value */ +#define RETSIGVAL @RETSIGVAL@ + +/* have sin_len field in sockaddr_in */ +#cmakedefine SIN_LEN + +/* The size of `long int', as computed by sizeof. */ +#define SIZEOF_LONG_INT @SIZEOF_LONG_INT@ + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@ + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P @SIZEOF_VOID_P@ + +/* should we declare syslog() and openlog() */ +#cmakedefine SYSLOG_INT + +/* Define to 1 if you have */ +#cmakedefine HAVE_SYS_TIME_H + +/* Define to 1 if you have */ +#cmakedefine HAVE_TIME_H + +/* Define to 1 if you can safely include both and . */ +#cmakedefine TIME_WITH_SYS_TIME + +/* Include Endace DAG support */ +#undef USE_DAG + +/* GeoIP geographic lookup functionality */ +#undef USE_GEOIP + +/* enable use of 64-bit integers */ +#cmakedefine USE_INT64 + +/* Use libclamav */ +#undef USE_LIBCLAMAV + +/* Use OpenSSL */ +#undef USE_OPENSSL + +/* Use Google's perftools */ +#undef USE_PERFTOOLS + +/* Use select-based main loop */ +#cmakedefine USE_SELECT_LOOP + +/* Version number of package */ +#define VERSION "@VERSION@" + +/* whether words are stored with the most significant byte first */ +#cmakedefine WORDS_BIGENDIAN + +/* ultrix can't hack const */ +#cmakedefine NEED_ULTRIX_CONST_HACK +#ifdef NEED_ULTRIX_CONST_HACK +#define const +#endif + +/* Define int32_t */ +#define int32_t @INT32_T@ + +/* use sigset() instead of signal() */ +#define signal @SIG_FUNC@ + +/* define to int if socklen_t not available */ +#define socklen_t @SOCKLEN_T@ + +/* Define u_int16_t */ +#define u_int16_t @U_INT16_T@ + +/* Define u_int32_t */ +#define u_int32_t @U_INT32_T@ + +/* Define u_int8_t */ +#define u_int8_t @U_INT8_T@ diff --git a/policy/CMakeLists.txt b/policy/CMakeLists.txt new file mode 100644 index 0000000000..be3bbcc6b6 --- /dev/null +++ b/policy/CMakeLists.txt @@ -0,0 +1,84 @@ +add_subdirectory(sigs) +add_subdirectory(time-machine) + + +########### install files ############### + +install(FILES bro.init adu.bro alarm.bro analy.bro anon.bro arp.bro backdoor.bro bittorrent.bro blaster.bro bt-tracker.bro brolite.bro brolite-backdoor.bro brolite-sigs.bro capture-events.bro capture-loss.bro capture-state-updates.bro checkpoint.bro clear-passwords.bro conn-flood.bro conn-id.bro conn.bro contents.bro cpu-adapt.bro dce.bro demux.bro detect-protocols.bro detect-protocols-http.bro dhcp.bro dns-anonymizer.bro dns-info.bro dns-lookup.bro dns.bro dpd.bro drop.bro drop-adapt.bro dyn-disable.bro file-flush.bro finger.bro firewall.bro flag-irc.bro flag-warez.bro frag.bro ftp-anonymizer.bro ftp-cmd-arg.bro ftp-reply-pattern.bro ftp-safe-words.bro ftp.bro gnutella.bro hand-over.bro heavy-analysis.bro heavy.http.bro heavy.irc.bro heavy.scan.bro heavy.software.bro heavy.trw.bro hot-ids.bro hot.bro http-abstract.bro http-anon-server.bro http-anon-useragent.bro http-anon-utils.bro http-anonymizer.bro http-body.bro http-detect-passwd.bro http-entity.bro http-event.bro http-extract-items.bro http-header.bro http-identified-files.bro http-reply.bro http-request.bro http-rewriter.bro http.bro icmp.bro ident-rewriter.bro ident.bro inactivity.bro interconn.bro irc.bro irc-bot.bro large-conns.bro listen-clear.bro listen-ssl.bro load-level.bro load-sample.bro log-append.bro login.bro mime.bro mime-pop.bro mt.bro ncp.bro netflow.bro netstats.bro nfs.bro notice.bro notice-policy.bro notice-action-filters.bro ntp.bro OS-fingerprint.bro pcap.bro peer-status.bro pkt-profile.bro pop3.bro port-name.bro portmapper.bro print-filter.bro print-globals.bro print-resources.bro print-sig-states.bro profiling.bro proxy.bro passwords.bro remote-pcap.bro remote-ping.bro remote-print-id-reply.bro remote-print-id.bro remote-print.bro remote-report-notices.bro remote-send-id.bro remote.bro rotate-logs.bro rsh.bro save-peer-status.bro scan.bro secondary-filter.bro sensor-sshd.bro server-ports.bro service-probe.bro signatures.bro site.bro smb.bro smtp-relay.bro smtp-rewriter.bro smtp.bro snort.bro software.bro ssh-stepping.bro ssh.bro ssl-alerts.bro ssl-ciphers.bro ssl-errors.bro ssl-worm.bro ssl.bro stats.bro stepping.bro synflood.bro targeted-scan.bro tcp.bro terminate-connection.bro tftp.bro trw.bro trw-impl.bro udp.bro udp-common.bro vlan.bro weird.bro worm.bro $(BIF_BRO_FILES) DESTINATION ${DATADIR}) +install(FILES DESTINATION ${DATADIR}) + + + +#original Makefile.am contents follow: + +### Process this file with automake to produce Makefile.in +# +#SUBDIRS = sigs time-machine +# +## These files are created and moved here by the src Makefile +#BIF_BRO_FILES = \ +# bro.bif.bro common-rw.bif.bro const.bif.bro \ +# dns-rw.bif.bro event.bif.bro finger-rw.bif.bro \ +# ftp-rw.bif.bro http-rw.bif.bro ident-rw.bif.bro \ +# smb-rw.bif.bro smtp-rw.bif.bro strings.bif.bro +# +#MOSTLYCLEANFILES = $(BIF_BRO_FILES) +# +## doesn't end in a sig +#bropolicydir=$(datadir)/bro +#bropolicysitedir=$(datadir)/bro/site +# +#dist_bropolicy_DATA = bro.init adu.bro alarm.bro analy.bro \ +# anon.bro arp.bro backdoor.bro bittorrent.bro \ +# blaster.bro bt-tracker.bro brolite.bro \ +# brolite-backdoor.bro brolite-sigs.bro \ +# capture-events.bro capture-loss.bro capture-state-updates.bro \ +# checkpoint.bro clear-passwords.bro conn-flood.bro conn-id.bro \ +# conn.bro contents.bro cpu-adapt.bro dce.bro demux.bro \ +# detect-protocols.bro detect-protocols-http.bro \ +# dhcp.bro dns-anonymizer.bro dns-info.bro \ +# dns-lookup.bro dns.bro dpd.bro drop.bro \ +# drop-adapt.bro dyn-disable.bro \ +# file-flush.bro finger.bro firewall.bro \ +# flag-irc.bro flag-warez.bro frag.bro \ +# ftp-anonymizer.bro ftp-cmd-arg.bro ftp-reply-pattern.bro \ +# ftp-safe-words.bro ftp.bro gnutella.bro hand-over.bro \ +# heavy-analysis.bro heavy.http.bro heavy.irc.bro \ +# heavy.scan.bro heavy.software.bro heavy.trw.bro \ +# hot-ids.bro hot.bro \ +# http-abstract.bro http-anon-server.bro http-anon-useragent.bro \ +# http-anon-utils.bro http-anonymizer.bro http-body.bro \ +# http-detect-passwd.bro http-entity.bro \ +# http-event.bro http-extract-items.bro http-header.bro \ +# http-identified-files.bro http-reply.bro \ +# http-request.bro http-rewriter.bro http.bro \ +# icmp.bro ident-rewriter.bro ident.bro inactivity.bro \ +# interconn.bro irc.bro irc-bot.bro large-conns.bro listen-clear.bro \ +# listen-ssl.bro load-level.bro load-sample.bro log-append.bro \ +# login.bro mime.bro mime-pop.bro mt.bro \ +# ncp.bro netflow.bro netstats.bro nfs.bro \ +# notice.bro notice-policy.bro notice-action-filters.bro ntp.bro \ +# OS-fingerprint.bro pcap.bro peer-status.bro \ +# pkt-profile.bro pop3.bro port-name.bro portmapper.bro print-filter.bro \ +# print-globals.bro print-resources.bro print-sig-states.bro \ +# profiling.bro proxy.bro passwords.bro \ +# remote-pcap.bro remote-ping.bro \ +# remote-print-id-reply.bro remote-print-id.bro remote-print.bro \ +# remote-report-notices.bro remote-send-id.bro remote.bro \ +# rotate-logs.bro rsh.bro \ +# save-peer-status.bro scan.bro secondary-filter.bro sensor-sshd.bro \ +# server-ports.bro service-probe.bro signatures.bro site.bro \ +# smb.bro smtp-relay.bro smtp-rewriter.bro smtp.bro snort.bro \ +# software.bro ssh-stepping.bro ssh.bro ssl-alerts.bro \ +# ssl-ciphers.bro ssl-errors.bro ssl-worm.bro ssl.bro stats.bro \ +# stepping.bro synflood.bro targeted-scan.bro tcp.bro \ +# terminate-connection.bro tftp.bro trw.bro trw-impl.bro \ +# udp.bro udp-common.bro vlan.bro weird.bro worm.bro \ +# $(BIF_BRO_FILES) +# +# +#install-data-hook: +# test -d $(DESTDIR)$(bropolicysitedir) || mkdir $(DESTDIR)$(bropolicysitedir) +# +#uninstall-local: +# -rmdir $(DESTDIR)$(bropolicysitedir) diff --git a/policy/sigs/CMakeLists.txt b/policy/sigs/CMakeLists.txt new file mode 100644 index 0000000000..8115bcaa85 --- /dev/null +++ b/policy/sigs/CMakeLists.txt @@ -0,0 +1,15 @@ + +########### install files ############### + +install(FILES dpd.sig ex.web-rules.sig http-bots.sig p0fsyn.osf snort-default.sig ssl-worm.sig worm.sig DESTINATION ${DATADIR}/sigs) + + + +#original Makefile.am contents follow: + +### Process this file with automake to produce Makefile.in +# +#sigsdir=${datadir}/bro/sigs +#dist_sigs_DATA = dpd.sig ex.web-rules.sig http-bots.sig p0fsyn.osf \ +# snort-default.sig ssl-worm.sig worm.sig +# diff --git a/policy/time-machine/CMakeLists.txt b/policy/time-machine/CMakeLists.txt new file mode 100644 index 0000000000..82f19fbf2f --- /dev/null +++ b/policy/time-machine/CMakeLists.txt @@ -0,0 +1,16 @@ + +########### install files ############### + +install(FILES time-machine.bro tm-capture.bro tm-class.bro tm-contents.bro tm-ftp.bro tm-gap.bro tm-http.bro DESTINATION ${DATADIR}/time-machine) + + + +#original Makefile.am contents follow: + +### Process this file with automake to produce Makefile.in +# +#tmdir=${datadir}/bro/time-machine +#dist_tm_DATA = \ +# time-machine.bro tm-capture.bro tm-class.bro tm-contents.bro \ +# tm-ftp.bro tm-gap.bro tm-http.bro +# diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000..0a5bcdcc57 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,387 @@ +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) +find_package(PCAP REQUIRED) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/binpac/lib + ${CMAKE_BINARY_DIR}/binpac/lib + ) + +find_program(SED_EXE sed) +if (NOT SED_EXE) + message(FATAL_ERROR "sed required") +endif () + +macro(REPLACE_YY_PREFIX_TARGET inFile outFile yylexPrefix yyPrefix) + set(args "'/extern char.*getenv/d\;s/yylex/${yylexPrefix}lex/\;s/yy/${yyPrefix}/g'" < ${inFile} > ${outFile}) + add_custom_command(OUTPUT ${outFile} + COMMAND ${SED_EXE} + ARGS ${args} + DEPENDS ${inFile} + COMMENT "[sed] replacing stuff in ${inFile}" + ) +endmacro(REPLACE_YY_PREFIX_TARGET) + +bison_target(BIFParser builtin-func.y + ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.cc + HEADER ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.h + COMPILE_FLAGS "-t") +flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc) +add_flex_bison_dependency(BIFScanner BIFParser) + +bison_target(RuleParser rule-parse.y + ${CMAKE_CURRENT_BINARY_DIR}/rup.cc + HEADER ${CMAKE_CURRENT_BINARY_DIR}/rup.h + COMPILE_FLAGS "-t") +replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rup.cc + ${CMAKE_CURRENT_BINARY_DIR}/rule-parse.cc + rules_ rules_) +replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rup.h + ${CMAKE_CURRENT_BINARY_DIR}/rule-parse.h + rules_ rules_) +flex_target(RuleScanner rule-scan.l ${CMAKE_CURRENT_BINARY_DIR}/rule-scan.cc + COMPILE_FLAGS "-Prules_") + +bison_target(REParser re-parse.y + ${CMAKE_CURRENT_BINARY_DIR}/rep.cc + HEADER ${CMAKE_CURRENT_BINARY_DIR}/re-parse.h + COMPILE_FLAGS "-t") +replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rep.cc + ${CMAKE_CURRENT_BINARY_DIR}/re-parse.cc + re_ RE_) +flex_target(REScanner re-scan.l ${CMAKE_CURRENT_BINARY_DIR}/re-scan.cc + COMPILE_FLAGS "-Pre_") +add_flex_bison_dependency(REScanner REParser) + +bison_target(Parser parse.bison.y + ${CMAKE_CURRENT_BINARY_DIR}/p.cc + HEADER ${CMAKE_CURRENT_BINARY_DIR}/broparse.h + COMPILE_FLAGS "-t") +replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/p.cc + ${CMAKE_CURRENT_BINARY_DIR}/parse.cc + bro yy) + +flex_target(Scanner scan.l ${CMAKE_CURRENT_BINARY_DIR}/scan.cc + COMPILE_FLAGS "-Pbro") + +configure_file (version.c.in ${CMAKE_CURRENT_BINARY_DIR}/version.c) + +########### next target ############### + +set(bifcl_SRCS + ${BISON_BIFParser_OUTPUTS} + ${FLEX_BIFScanner_OUTPUTS} + bif_arg.cc +) + +add_executable(bifcl ${bifcl_SRCS}) + +target_link_libraries(bifcl) + +macro(BIF_TARGET bifInput) + get_bif_output_files(${bifInput} bifOutputs) + add_custom_command(OUTPUT ${bifOutputs} + COMMAND bifcl + ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${bifInput} + DEPENDS ${bifInput} + COMMENT "[BIFCL] Processing ${bifInput}" + ) + list(APPEND ALL_BIF_OUTPUTS ${bifOutputs}) +endmacro(BIF_TARGET) + +macro(GET_BIF_OUTPUT_FILES inputFile outputFileVar) + set(${outputFileVar} + ${CMAKE_CURRENT_BINARY_DIR}/${inputFile}.bro + ${CMAKE_CURRENT_BINARY_DIR}/${inputFile}.func_def + ${CMAKE_CURRENT_BINARY_DIR}/${inputFile}.func_h + ${CMAKE_CURRENT_BINARY_DIR}/${inputFile}.func_init + ${CMAKE_CURRENT_BINARY_DIR}/${inputFile}.netvar_def + ${CMAKE_CURRENT_BINARY_DIR}/${inputFile}.netvar_h + ${CMAKE_CURRENT_BINARY_DIR}/${inputFile}.netvar_init + ) +endmacro(GET_BIF_OUTPUT_FILES) + +########## targets that needed bifcl ########## + +set(BIF_SRCS + bro.bif + event.bif + const.bif + common-rw.bif + finger-rw.bif + ident-rw.bif + dns-rw.bif + ftp-rw.bif + smtp-rw.bif + http-rw.bif + strings.bif + smb-rw.bif + ) + +foreach(bift ${BIF_SRCS}) + bif_target(${bift}) +endforeach(bift) + + +########## targets that need binpac ########## + +#TODO: need logic to find binpac when it's a separate component? + +macro(BINPAC_TARGET pacFile) + get_filename_component(basename ${pacFile} NAME_WE) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.h + ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.cc + COMMAND binpac + ARGS -d ${CMAKE_CURRENT_BINARY_DIR} + -I ${CMAKE_CURRENT_SOURCE_DIR} + ${pacFile} + DEPENDS binpac ${pacFile} + COMMENT "[BINPAC] Processing ${pacFile}" + ) + list(APPEND ALL_BINPAC_OUTPUTS + ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.h + ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.cc) +endmacro(BINPAC_TARGET) + +set(BINPAC_SRCS + binpac-lib.pac + binpac_bro-lib.pac + bittorrent.pac + dce_rpc.pac + dce_rpc_simple.pac + dhcp.pac + dns.pac + dns_tcp.pac + http.pac + ncp.pac + netflow.pac + rpc.pac + smb.pac + ssl.pac + ssl-record-layer.pac +) + +set(BINPAC_AUXSRC + binpac.pac + bro.pac + binpac_bro.h +) + +set(BINPAC_RPC_AUXSRC + bittorrent-protocol.pac bittorrent-analyzer.pac + dce_rpc-analyzer.pac dce_rpc-protocol.pac + dhcp-analyzer.pac dhcp-protocol.pac + dns-analyzer.pac dns-protocol.pac + epmapper.pac + http-analyzer.pac http-protocol.pac http.pac + netflow-protocol.pac netflow-analyzer.pac + portmap-protocol.pac portmap-analyzer.pac + rpc-protocol.pac rpc-analyzer.pac + smb-protocol.pac smb-mailslot.pac smb-pipe.pac + ssl.pac ssl-analyzer.pac ssl-defs.pac + ssl-protocol.pac ssl-record-layer.pac +) + +foreach(binpact ${BINPAC_SRCS}) + binpac_target(${CMAKE_CURRENT_SOURCE_DIR}/${binpact}) +endforeach(binpact) + +########### next target ############### + +if (HAVE_NB_DNS) + set(dns_SRCS nb_dns.c nb_dns.h) +endif () + +if (USE_OPENSSL) + set(openssl_SRCS X509.cc SSLCiphers.cc SSLInterpreter.cc SSLProxy.cc + SSLv2.cc SSLv3.cc SSLv3Automaton.cc) +endif () + +if (USE_NMALLOC) + set(malloc_SRCS malloc.c) +endif () + +find_program(PERL_EXE perl) +if (NOT PERL_EXE) + message(FATAL_ERROR "perl required") +endif () + +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/DebugCmdConstants.h + ${CMAKE_CURRENT_BINARY_DIR}/DebugCmdInfoConstants.h + COMMAND ${PERL_EXE} + ARGS ${CMAKE_CURRENT_SOURCE_DIR}/make_dbg_constants.pl + ${CMAKE_CURRENT_SOURCE_DIR}/DebugCmdInfoConstants.in + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/DebugCmdInfoConstants.in + COMMENT "[Perl] Processing debug commands" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +add_custom_target(make_dbg_constants DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/DebugCmdConstants.h + ${CMAKE_CURRENT_BINARY_DIR}/DebugCmdInfoConstants.h) + +set(bro_SRCS + ${BINPAC_AUXSRC} + ${BINPAC_RPC_AUXSRC} + ${ALL_BIF_OUTPUTS} + ${ALL_BINPAC_OUTPUTS} + ${CMAKE_CURRENT_BINARY_DIR}/version.c + rule-parse.cc + rule-parse.h + ${FLEX_RuleScanner_OUTPUTS} + re-parse.cc + ${FLEX_REScanner_OUTPUTS} + parse.cc + ${FLEX_Scanner_OUTPUTS} + main.cc + net_util.cc + util.cc + Active.cc + Analyzer.cc + Anon.cc + ARP.cc + Attr.cc + BackDoor.cc + Base64.cc + BitTorrent.cc + BitTorrentTracker.cc + BPF_Program.cc + BroString.cc + CCL.cc + ChunkedIO.cc + CompHash.cc + Conn.cc + ConnCompressor.cc + ContentLine.cc + DCE_RPC.cc + DFA.cc + DHCP-binpac.cc + DNS.cc + DNS-binpac.cc + DNS_Mgr.cc + DbgBreakpoint.cc + DbgHelp.cc + DbgWatch.cc + Debug.cc + DebugCmds.cc + DebugLogger.cc + Desc.cc + Dict.cc + Discard.cc + DPM.cc + EquivClass.cc + Event.cc + EventHandler.cc + EventLauncher.cc + EventRegistry.cc + Expr.cc + FTP.cc + File.cc + FileAnalyzer.cc + Finger.cc + FlowSrc.cc + Frag.cc + Frame.cc + Func.cc + Gnutella.cc + HTTP.cc + HTTP-binpac.cc + Hash.cc + ICMP.cc + ID.cc + Ident.cc + IntSet.cc + InterConn.cc + IOSource.cc + IRC.cc + List.cc + Logger.cc + Login.cc + MIME.cc + NCP.cc + NFA.cc + NFS.cc + NTP.cc + NVT.cc + Net.cc + NetVar.cc + NetbiosSSN.cc + Obj.cc + OSFinger.cc + PacketFilter.cc + PacketSort.cc + PersistenceSerializer.cc + PktDagSrc.cc + PktSrc.cc + PIA.cc + PolicyFile.cc + POP3.cc + Portmap.cc + PrefixTable.cc + PriorityQueue.cc + Queue.cc + RE.cc + RPC.cc + Reassem.cc + RemoteSerializer.cc + Rlogin.cc + RSH.cc + Rule.cc + RuleAction.cc + RuleCondition.cc + RuleMatcher.cc + ScriptAnaly.cc + SmithWaterman.cc + SMB.cc + SMTP.cc + SSH.cc + SSL-binpac.cc + Scope.cc + SerializationFormat.cc + SerialObj.cc + Serializer.cc + Sessions.cc + StateAccess.cc + Stats.cc + SteppingStone.cc + Stmt.cc + TCP.cc + TCP_Endpoint.cc + TCP_Reassembler.cc + TCP_Rewriter.cc + Telnet.cc + Timer.cc + Traverse.cc + Trigger.cc + TwoWise.cc + Type.cc + UDP.cc + Val.cc + Var.cc + XDR.cc + ZIP.cc + bsd-getopt-long.c + cq.c + md5.c + patricia.c + setsignal.c + UDP_Rewriter.cc + DNS_Rewriter.cc + PacketDumper.cc + Rewriter.cc + strsep.c + ${dns_SRCS} + ${malloc_SRCS} + ${openssl_SRCS} +) + +add_definitions(-DPOLICYDEST="${DATADIR}/bro/") + +add_executable(bro ${bro_SRCS}) + +add_dependencies(bro make_dbg_constants) + +target_link_libraries(bro m binpac_lib ${PCAP_LIBRARY} resolv) + +install(TARGETS bro DESTINATION bin) diff --git a/src/parse.bison.y b/src/parse.bison.y new file mode 100644 index 0000000000..b0bb39f0ea --- /dev/null +++ b/src/parse.bison.y @@ -0,0 +1,1308 @@ +%{ +// $Id: parse.in 6688 2009-04-16 22:44:55Z vern $ +// See the file "COPYING" in the main distribution directory for copyright. +%} + +%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ALARM TOK_ANY +%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF +%token TOK_BOOL TOK_BREAK TOK_CASE TOK_CONST +%token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_COUNTER TOK_DEFAULT TOK_DELETE +%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FILE TOK_FOR +%token TOK_FUNCTION TOK_GLOBAL TOK_GLOBAL_ATTR TOK_ID TOK_IF TOK_INT +%token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE TOK_MATCH TOK_NET +%token TOK_NEXT TOK_OF TOK_PATTERN TOK_PATTERN_TEXT +%token TOK_PORT TOK_PRINT TOK_RECORD TOK_REDEF +%token TOK_REMOVE_FROM TOK_RETURN TOK_SCHEDULE TOK_SET +%token TOK_STRING TOK_SUBNET TOK_SWITCH TOK_TABLE TOK_THIS +%token TOK_TIME TOK_TIMEOUT TOK_TIMER TOK_TYPE TOK_UNION TOK_VECTOR TOK_WHEN + +%token TOK_ATTR_ADD_FUNC TOK_ATTR_ATTR TOK_ATTR_ENCRYPT TOK_ATTR_DEFAULT +%token TOK_ATTR_OPTIONAL TOK_ATTR_REDEF TOK_ATTR_ROTATE_INTERVAL +%token TOK_ATTR_ROTATE_SIZE TOK_ATTR_DEL_FUNC TOK_ATTR_EXPIRE_FUNC +%token TOK_ATTR_EXPIRE_CREATE TOK_ATTR_EXPIRE_READ TOK_ATTR_EXPIRE_WRITE +%token TOK_ATTR_PERSISTENT TOK_ATTR_SYNCHRONIZED +%token TOK_ATTR_DISABLE_PRINT_HOOK TOK_ATTR_RAW_OUTPUT TOK_ATTR_MERGEABLE +%token TOK_ATTR_PRIORITY TOK_ATTR_GROUP + +%token TOK_DEBUG + +%left ',' '|' +%right '=' TOK_ADD_TO TOK_REMOVE_FROM +%right '?' ':' TOK_USING +%left TOK_OR +%left TOK_AND +%nonassoc '<' '>' TOK_LE TOK_GE TOK_EQ TOK_NE +%left TOK_IN TOK_NOT_IN +%left '+' '-' +%left '*' '/' '%' +%left TOK_INCR TOK_DECR +%right '!' +%left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR + +%type TOK_ID TOK_PATTERN_TEXT single_pattern +%type local_id global_id event_id global_or_event_id resolve_id begin_func +%type local_id_list +%type init_class +%type opt_init +%type TOK_CONSTANT +%type pattern +%type expr init anonymous_function +%type event +%type stmt stmt_list func_body for_head +%type type opt_type refined_type enum_id_list +%type func_hdr func_params +%type type_list +%type type_decl formal_args_decl +%type type_decl_list formal_args_decl_list opt_attr_attr +%type formal_args +%type expr_list opt_expr_list +%type case +%type case_list +%type attr +%type attr_list opt_attr + +%{ +#include +#include +#include + +#include "input.h" +#include "Expr.h" +#include "Stmt.h" +#include "Var.h" +#include "DNS.h" +#include "RE.h" +#include "Scope.h" + +YYLTYPE GetCurrentLocation(); +extern int yyerror(const char[]); +extern int brolex(); + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + (Current) = (Rhs)[(N)]; + +/* + * Part of the module facility: while parsing, keep track of which + * module to put things in. + */ +string current_module = GLOBAL_MODULE_NAME; +bool is_export = false; // true if in an export {} block + +/* + * When parsing an expression for the debugger, where to put the result + * (obviously not reentrant). + */ +extern Expr* g_curr_debug_expr; + +#define YYLTYPE yyltype + +Expr* bro_this = 0; +int in_init = 0; +bool in_debug = false; +bool resolving_global_ID = false; + +ID* func_id = 0; +%} + +%union { + char* str; + ID* id; + id_list* id_l; + init_class ic; + Val* val; + RE_Matcher* re; + Expr* expr; + CallExpr* call_expr; + EventExpr* event_expr; + Stmt* stmt; + ListExpr* list; + BroType* type; + RecordType* record; + FuncType* func_type; + TypeList* type_l; + TypeDecl* type_decl; + type_decl_list* type_decl_l; + Case* c_case; + case_list* case_l; + Attr* attr; + attr_list* attr_l; + attr_tag attrtag; +} + +%% + +bro: + decl_list stmt_list + { + if ( optimize ) + $2 = $2->Simplify(); + + if ( stmts ) + stmts->AsStmtList()->Stmts().append($2); + else + stmts = $2; + + // Any objects creates from hereon out should not + // have file positions associated with them. + set_location(no_location); + } + | + /* Silly way of allowing the debugger to call yyparse() + * on an expr rather than a file. + */ + TOK_DEBUG { in_debug = true; } expr + { + g_curr_debug_expr = $3; + in_debug = false; + } + ; + +decl_list: + decl_list decl + | + ; + +expr: + '(' expr ')' + { + set_location(@1, @3); + $$ = $2; $$->MarkParen(); + } + + | TOK_COPY '(' expr ')' + { + set_location(@1, @4); + $$ = new CloneExpr($3); + } + + | TOK_INCR expr + { + set_location(@1, @2); + $$ = new IncrExpr(EXPR_INCR, $2); + } + + | TOK_DECR expr + { + set_location(@1, @2); + $$ = new IncrExpr(EXPR_DECR, $2); + } + + | '!' expr + { + set_location(@1, @2); + $$ = new NotExpr($2); + } + + | '-' expr %prec '!' + { + set_location(@1, @2); + $$ = new NegExpr($2); + } + + | '+' expr %prec '!' + { + set_location(@1, @2); + $$ = new PosExpr($2); + } + + | expr '+' expr + { + set_location(@1, @3); + $$ = new AddExpr($1, $3); + } + + | expr TOK_ADD_TO expr + { + set_location(@1, @3); + $$ = new AddToExpr($1, $3); + } + + | expr '-' expr + { + set_location(@1, @3); + $$ = new SubExpr($1, $3); + } + + | expr TOK_REMOVE_FROM expr + { + set_location(@1, @3); + $$ = new RemoveFromExpr($1, $3); + } + + | expr '*' expr + { + set_location(@1, @3); + $$ = new TimesExpr($1, $3); + } + + | expr '/' expr + { + set_location(@1, @3); + $$ = new DivideExpr($1, $3); + } + + | expr '%' expr + { + set_location(@1, @3); + $$ = new ModExpr($1, $3); + } + + | expr TOK_AND expr + { + set_location(@1, @3); + $$ = new BoolExpr(EXPR_AND, $1, $3); + } + + | expr TOK_OR expr + { + set_location(@1, @3); + $$ = new BoolExpr(EXPR_OR, $1, $3); + } + + | expr TOK_EQ expr + { + set_location(@1, @3); + $$ = new EqExpr(EXPR_EQ, $1, $3); + } + + | expr TOK_NE expr + { + set_location(@1, @3); + $$ = new EqExpr(EXPR_NE, $1, $3); + } + + | expr '<' expr + { + set_location(@1, @3); + $$ = new RelExpr(EXPR_LT, $1, $3); + } + + | expr TOK_LE expr + { + set_location(@1, @3); + $$ = new RelExpr(EXPR_LE, $1, $3); + } + + | expr '>' expr + { + set_location(@1, @3); + $$ = new RelExpr(EXPR_GT, $1, $3); + } + + | expr TOK_GE expr + { + set_location(@1, @3); + $$ = new RelExpr(EXPR_GE, $1, $3); + } + + | expr '?' expr ':' expr + { + set_location(@1, @5); + $$ = new CondExpr($1, $3, $5); + } + + | expr '=' expr + { + set_location(@1, @3); + $$ = get_assign_expr($1, $3, in_init); + } + + | TOK_LOCAL local_id '=' expr + { + set_location(@2, @4); + $$ = add_and_assign_local($2, $4, new Val(1, TYPE_BOOL)); + } + + | expr '[' expr_list ']' + { + set_location(@1, @4); + $$ = new IndexExpr($1, $3); + } + + | expr '$' TOK_ID + { + set_location(@1, @3); + $$ = new FieldExpr($1, $3); + } + + | '$' TOK_ID '=' expr + { + set_location(@1, @4); + $$ = new FieldAssignExpr($2, $4); + } + + | '$' TOK_ID func_params '=' + { + func_id = current_scope()->GenerateTemporary("anonymous-function"); + func_id->SetInferReturnType(true); + begin_func(func_id, + current_module.c_str(), + FUNC_FLAVOR_FUNCTION, + 0, + $3); + } + func_body + { + $$ = new FieldAssignExpr($2, new ConstExpr(func_id->ID_Val())); + } + + | expr TOK_IN expr + { + set_location(@1, @3); + $$ = new InExpr($1, $3); + } + + | expr TOK_NOT_IN expr + { + set_location(@1, @3); + $$ = new NotExpr(new InExpr($1, $3)); + } + + | '[' expr_list ']' + { + // A little crufty: we peek at the type of + // the first expression in the list. If it's + // a record or a field assignment, then this + // is a record constructor. If not, then this + // is a list used for an initializer. + + set_location(@1, @3); + + Expr* e0 = $2->Exprs()[0]; + if ( e0->Tag() == EXPR_FIELD_ASSIGN || + e0->Type()->Tag() == TYPE_RECORD ) + $$ = new RecordConstructorExpr($2); + else + $$ = $2; + } + + + | TOK_RECORD '(' expr_list ')' + { + set_location(@1, @4); + $$ = new RecordConstructorExpr($3); + } + + | TOK_TABLE '(' { ++in_init; } opt_expr_list ')' { --in_init; } + opt_attr + { // the ++in_init fixes up the parsing of "[x] = y" + set_location(@1, @5); + $$ = new TableConstructorExpr($4, $7); + } + + | TOK_SET '(' opt_expr_list ')' opt_attr + { + set_location(@1, @4); + $$ = new SetConstructorExpr($3, $5); + } + + | TOK_VECTOR '(' opt_expr_list ')' + { + set_location(@1, @4); + $$ = new VectorConstructorExpr($3); + } + + | TOK_MATCH expr TOK_USING expr + { + set_location(@1, @4); + $$ = new RecordMatchExpr($2, $4); + } + + | expr '(' opt_expr_list ')' + { + set_location(@1, @4); + $$ = new CallExpr($1, $3); + } + + | expr TOK_HAS_FIELD TOK_ID + { + set_location(@1, @3); + $$ = new HasFieldExpr($1, $3, false); + } + + | expr TOK_HAS_ATTR TOK_ID + { + set_location(@1, @3); + $$ = new HasFieldExpr($1, $3, true); + } + + | anonymous_function + + | TOK_SCHEDULE expr '{' event '}' + { + set_location(@1, @5); + $$ = new ScheduleExpr($2, $4); + } + + | TOK_ID + { + set_location(@1); + + ID* id = lookup_ID($1, current_module.c_str()); + if ( ! id ) + { + if ( ! in_debug ) + { +/* // CHECK THAT THIS IS NOT GLOBAL. + id = install_ID($1, current_module.c_str(), + false, is_export); +*/ + + yyerror(fmt("unknown identifier %s", $1)); + YYERROR; + } + else + { + yyerror(fmt("unknown identifier %s", $1)); + YYERROR; + } + } + else + { + if ( ! id->Type() ) + { + id->Error("undeclared variable"); + id->SetType(error_type()); + $$ = new NameExpr(id); + } + + else if ( id->IsEnumConst() ) + { + EnumType* t = id->Type()->AsEnumType(); + int intval = t->Lookup(id->ModuleName(), + id->Name()); + if ( intval < 0 ) + internal_error("enum value not found for %s", id->Name()); + $$ = new ConstExpr(new EnumVal(intval, t)); + } + else + $$ = new NameExpr(id); + } + } + + | TOK_CONSTANT + { + set_location(@1); + $$ = new ConstExpr($1); + } + + | pattern + { + set_location(@1); + $1->Compile(); + $$ = new ConstExpr(new PatternVal($1)); + } + + | TOK_THIS + { + set_location(@1); + $$ = bro_this->Ref(); + } + + | '|' expr '|' + { + set_location(@1, @3); + $$ = new SizeExpr($2); + } + ; + +expr_list: + expr_list ',' expr + { + set_location(@1, @3); + $1->Append($3); + } + + | expr + { + set_location(@1); + $$ = new ListExpr($1); + } + ; + +opt_expr_list: + expr_list + | + { $$ = new ListExpr(); } + ; + +opt_comma: + ',' + | + ; + +pattern: + pattern '|' single_pattern + { + $1->AddPat($3); + delete [] $3; + } + + | single_pattern + { + $$ = new RE_Matcher($1); + delete [] $1; + } + ; + +single_pattern: + '/' { begin_RE(); } TOK_PATTERN_TEXT { end_RE(); } '/' + { $$ = $3; } + ; + +enum_id_list: + TOK_ID + { + set_location(@1); + + EnumType* et = new EnumType(is_export); + if ( et->AddName(current_module, $1) < 0 ) + error("identifier in enumerated type definition already exists"); + $$ = et; + } + + | enum_id_list ',' TOK_ID + { + set_location(@1, @3); + + if ( $1->AsEnumType()->AddName(current_module, $3) < 1 ) + error("identifier in enumerated type definition already exists"); + $$ = $1; + } + ; + +type: + TOK_BOOL { + set_location(@1); + $$ = base_type(TYPE_BOOL); + } + + | TOK_INT { + set_location(@1); + $$ = base_type(TYPE_INT); + } + + | TOK_COUNT { + set_location(@1); + $$ = base_type(TYPE_COUNT); + } + + | TOK_COUNTER { + set_location(@1); + $$ = base_type(TYPE_COUNTER); + } + + | TOK_DOUBLE { + set_location(@1); + $$ = base_type(TYPE_DOUBLE); + } + + | TOK_TIME { + set_location(@1); + $$ = base_type(TYPE_TIME); + } + + | TOK_INTERVAL { + set_location(@1); + $$ = base_type(TYPE_INTERVAL); + } + + | TOK_STRING { + set_location(@1); + $$ = base_type(TYPE_STRING); + } + + | TOK_PATTERN { + set_location(@1); + $$ = base_type(TYPE_PATTERN); + } + + | TOK_TIMER { + set_location(@1); + $$ = base_type(TYPE_TIMER); + } + + | TOK_PORT { + set_location(@1); + $$ = base_type(TYPE_PORT); + } + + | TOK_ADDR { + set_location(@1); + $$ = base_type(TYPE_ADDR); + } + + | TOK_NET { + set_location(@1); + $$ = base_type(TYPE_NET); + } + + | TOK_SUBNET { + set_location(@1); + $$ = base_type(TYPE_SUBNET); + } + + | TOK_ANY { + set_location(@1); + $$ = base_type(TYPE_ANY); + } + + | TOK_TABLE '[' type_list ']' TOK_OF type + { + set_location(@1, @6); + $$ = new TableType($3, $6); + } + + | TOK_SET '[' type_list ']' + { + set_location(@1, @4); + $$ = new SetType($3, 0); + } + + | TOK_RECORD '{' type_decl_list '}' + { + set_location(@1, @4); + $$ = new RecordType($3); + } + + | TOK_UNION '{' type_list '}' + { + set_location(@1, @4); + error("union type not implemented"); + $$ = 0; + } + + | TOK_ENUM '{' enum_id_list opt_comma '}' + { + set_location(@1, @4); + $$ = $3; + } + + | TOK_LIST + { + set_location(@1); + // $$ = new TypeList(); + error("list type not implemented"); + $$ = 0; + } + + | TOK_LIST TOK_OF type + { + set_location(@1); + // $$ = new TypeList($3); + error("list type not implemented"); + $$ = 0; + } + + | TOK_VECTOR TOK_OF type + { + set_location(@1, @3); + $$ = new VectorType($3); + } + + | TOK_FUNCTION func_params + { + set_location(@1, @2); + $$ = $2; + } + + | TOK_EVENT '(' formal_args ')' + { + set_location(@1, @3); + $$ = new FuncType($3, 0, 1); + } + + | TOK_FILE TOK_OF type + { + set_location(@1, @3); + $$ = new FileType($3); + } + + | TOK_FILE + { + set_location(@1); + $$ = new FileType(base_type(TYPE_STRING)); + } + + | resolve_id + { + if ( ! $1 || ! ($$ = $1->AsType()) ) + { + NullStmt here; + if ( $1 ) + $1->Error("not a BRO type", &here); + $$ = error_type(); + } + else + Ref($$); + } + ; + +type_list: + type_list ',' type + { $1->AppendEvenIfNotPure($3); } + | type + { + $$ = new TypeList($1); + $$->Append($1); + } + ; + +type_decl_list: + type_decl_list type_decl + { $1->append($2); } + | + { $$ = new type_decl_list(); } + ; + +type_decl: + TOK_ID ':' type opt_attr ';' + { + set_location(@1, @5); + $$ = new TypeDecl($3, $1, $4); + } + ; + +formal_args: + formal_args_decl_list + { $$ = new RecordType($1); } + | formal_args_decl_list ';' + { $$ = new RecordType($1); } + | + { $$ = new RecordType(new type_decl_list()); } + ; + +formal_args_decl_list: + formal_args_decl_list ';' formal_args_decl + { $1->append($3); } + | formal_args_decl_list ',' formal_args_decl + { $1->append($3); } + | formal_args_decl + { $$ = new type_decl_list(); $$->append($1); } + ; + +formal_args_decl: + TOK_ID ':' type opt_attr + { + set_location(@1, @4); + $$ = new TypeDecl($3, $1, $4); + } + ; + +decl: + TOK_MODULE TOK_ID ';' + { current_module = $2; } + + | TOK_EXPORT '{' { is_export = true; } decl_list '}' + { is_export = false; } + + | TOK_GLOBAL global_id opt_type init_class opt_init opt_attr ';' + { add_global($2, $3, $4, $5, $6, VAR_REGULAR); } + + | TOK_CONST global_id opt_type init_class opt_init opt_attr ';' + { add_global($2, $3, $4, $5, $6, VAR_CONST); } + + | TOK_REDEF global_id opt_type init_class opt_init opt_attr ';' + { add_global($2, $3, $4, $5, $6, VAR_REDEF); } + + | TOK_REDEF TOK_ENUM global_id TOK_ADD_TO + '{' enum_id_list opt_comma '}' ';' + { + if ( ! $3->Type() ) + $3->Error("unknown identifier"); + else + { + EnumType* add_to = $3->Type()->AsEnumType(); + if ( ! add_to ) + $3->Error("not an enum"); + else + add_to->AddNamesFrom(current_module, + $6->AsEnumType()); + } + } + + | TOK_TYPE global_id ':' refined_type opt_attr opt_attr_attr ';' + { + add_type($2, $4, $5, 0); + if ( $6 ) + $2->AsType()->SetAttributesType($6); + } + + | TOK_GLOBAL_ATTR ':' { in_global_attr_decl = true; } + '{' type_decl_list '}' ';' { in_global_attr_decl = false; } + { + global_attributes_type = new RecordType($5); + } + + | TOK_EVENT event_id ':' refined_type opt_attr ';' + { add_type($2, $4, $5, 1); } + + | func_hdr func_body + { } + + | conditional + ; + +conditional: + TOK_ATIF '(' expr ')' + { do_atif($3); } + | TOK_ATIFDEF '(' TOK_ID ')' + { do_atifdef($3); } + | TOK_ATIFNDEF '(' TOK_ID ')' + { do_atifndef($3); } + | TOK_ATENDIF + { do_atendif(); } + | TOK_ATELSE + { do_atelse(); } + ; + +opt_attr_attr: + TOK_ATTR_ATTR '=' '{' type_decl_list '}' + { $$ = $4; } + | + { $$ = 0; } + ; + +func_hdr: + TOK_FUNCTION global_id func_params + { + begin_func($2, current_module.c_str(), + FUNC_FLAVOR_FUNCTION, 0, $3); + $$ = $3; + } + | TOK_EVENT event_id func_params + { + begin_func($2, current_module.c_str(), + FUNC_FLAVOR_EVENT, 0, $3); + $$ = $3; + } + | TOK_REDEF TOK_EVENT event_id func_params + { + begin_func($3, current_module.c_str(), + FUNC_FLAVOR_EVENT, 1, $4); + $$ = $4; + } + ; + +func_body: + opt_attr '{' stmt_list '}' + { + if ( optimize ) + $3 = $3->Simplify(); + + end_func($3, $1); + } + ; + +anonymous_function: + TOK_FUNCTION begin_func func_body + { $$ = new ConstExpr($2->ID_Val()); } + ; + +begin_func: + func_params + { + $$ = current_scope()->GenerateTemporary("anonymous-function"); + begin_func($$, current_module.c_str(), + FUNC_FLAVOR_FUNCTION, 0, $1); + } + ; + +func_params: + '(' formal_args ')' ':' type + { $$ = new FuncType($2, $5, 0); } + | '(' formal_args ')' + { $$ = new FuncType($2, base_type(TYPE_VOID), 0); } + ; + +refined_type: + type_list '{' type_decl_list '}' + { $$ = refine_type($1, $3); } + | type_list + { $$ = refine_type($1, 0); } + ; + +opt_type: + ':' type + { $$ = $2; } + | + { $$ = 0; } + ; + +init_class: + { $$ = INIT_NONE; } + | '=' { $$ = INIT_FULL; } + | TOK_ADD_TO { $$ = INIT_EXTRA; } + | TOK_REMOVE_FROM { $$ = INIT_REMOVE; } + ; + +opt_init: + { ++in_init; } init { --in_init; } + { $$ = $2; } + | + { $$ = 0; } + ; + +init: + '{' opt_expr_list '}' + { $$ = $2; } + | '{' expr_list ',' '}' + { $$ = $2; } + | expr + ; + +opt_attr: + attr_list + | + { $$ = 0; } + ; + +attr_list: + attr_list attr + { $1->append($2); } + | attr + { + $$ = new attr_list; + $$->append($1); + } + ; + +attr: + TOK_ATTR_DEFAULT '=' expr + { $$ = new Attr(ATTR_DEFAULT, $3); } + | TOK_ATTR_OPTIONAL + { $$ = new Attr(ATTR_OPTIONAL); } + | TOK_ATTR_REDEF + { $$ = new Attr(ATTR_REDEF); } + | TOK_ATTR_ROTATE_INTERVAL '=' expr + { $$ = new Attr(ATTR_ROTATE_INTERVAL, $3); } + | TOK_ATTR_ROTATE_SIZE '=' expr + { $$ = new Attr(ATTR_ROTATE_SIZE, $3); } + | TOK_ATTR_ADD_FUNC '=' expr + { $$ = new Attr(ATTR_ADD_FUNC, $3); } + | TOK_ATTR_DEL_FUNC '=' expr + { $$ = new Attr(ATTR_DEL_FUNC, $3); } + | TOK_ATTR_EXPIRE_FUNC '=' expr + { $$ = new Attr(ATTR_EXPIRE_FUNC, $3); } + | TOK_ATTR_EXPIRE_CREATE '=' expr + { $$ = new Attr(ATTR_EXPIRE_CREATE, $3); } + | TOK_ATTR_EXPIRE_READ '=' expr + { $$ = new Attr(ATTR_EXPIRE_READ, $3); } + | TOK_ATTR_EXPIRE_WRITE '=' expr + { $$ = new Attr(ATTR_EXPIRE_WRITE, $3); } + | TOK_ATTR_PERSISTENT + { $$ = new Attr(ATTR_PERSISTENT); } + | TOK_ATTR_SYNCHRONIZED + { $$ = new Attr(ATTR_SYNCHRONIZED); } + | TOK_ATTR_ENCRYPT + { $$ = new Attr(ATTR_ENCRYPT); } + | TOK_ATTR_ENCRYPT '=' expr + { $$ = new Attr(ATTR_ENCRYPT, $3); } + | TOK_ATTR_DISABLE_PRINT_HOOK + { $$ = new Attr(ATTR_DISABLE_PRINT_HOOK); } + | TOK_ATTR_RAW_OUTPUT + { $$ = new Attr(ATTR_RAW_OUTPUT); } + | TOK_ATTR_MERGEABLE + { $$ = new Attr(ATTR_MERGEABLE); } + | TOK_ATTR_PRIORITY '=' expr + { $$ = new Attr(ATTR_PRIORITY, $3); } + | TOK_ATTR_GROUP '=' expr + { $$ = new Attr(ATTR_GROUP, $3); } + ; + +stmt: + '{' stmt_list '}' + { + set_location(@1, @3); + $$ = $2; + } + + | TOK_ALARM expr_list ';' + { + set_location(@1, @3); + $$ = new AlarmStmt($2); + } + + | TOK_PRINT expr_list ';' + { + set_location(@1, @3); + $$ = new PrintStmt($2); + } + + | TOK_EVENT event ';' + { + set_location(@1, @3); + $$ = new EventStmt($2); + } + + | TOK_IF '(' expr ')' stmt + { + set_location(@1, @4); + $$ = new IfStmt($3, $5, new NullStmt()); + } + + | TOK_IF '(' expr ')' stmt TOK_ELSE stmt + { + set_location(@1, @4); + $$ = new IfStmt($3, $5, $7); + } + + | TOK_SWITCH expr '{' case_list '}' + { + set_location(@1, @2); + $$ = new SwitchStmt($2, $4); + } + + | for_head stmt + { $1->AsForStmt()->AddBody($2); } + + | TOK_NEXT ';' + { + set_location(@1, @2); + $$ = new NextStmt; + } + + | TOK_BREAK ';' + { + set_location(@1, @2); + $$ = new BreakStmt; + } + + | TOK_RETURN ';' + { + set_location(@1, @2); + $$ = new ReturnStmt(0); + } + + | TOK_RETURN expr ';' + { + set_location(@1, @2); + $$ = new ReturnStmt($2); + } + + | TOK_ADD expr ';' + { + set_location(@1, @3); + $$ = new AddStmt($2); + } + + | TOK_DELETE expr ';' + { + set_location(@1, @3); + $$ = new DelStmt($2); + } + + | TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' + { + set_location(@1, @7); + $$ = add_local($2, $3, $4, $5, $6, VAR_REGULAR); + } + + | TOK_CONST local_id opt_type init_class opt_init opt_attr ';' + { + set_location(@1, @6); + $$ = add_local($2, $3, $4, $5, $6, VAR_CONST); + } + + | TOK_WHEN '(' expr ')' stmt + { + set_location(@3, @5); + $$ = new WhenStmt($3, $5, 0, 0, false); + } + + | TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' stmt_list '}' + { + set_location(@3, @8); + $$ = new WhenStmt($3, $5, $9, $7, false); + } + + + | TOK_RETURN TOK_WHEN '(' expr ')' stmt + { + set_location(@4, @6); + $$ = new WhenStmt($4, $6, 0, 0, true); + } + + | TOK_RETURN TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' stmt_list '}' + { + set_location(@4, @9); + $$ = new WhenStmt($4, $6, $10, $8, true); + } + + | expr ';' + { + set_location(@1, @2); + $$ = new ExprStmt($1); + } + + | ';' + { + set_location(@1, @1); + $$ = new NullStmt; + } + + | conditional + { $$ = new NullStmt; } + ; + +stmt_list: + stmt_list stmt + { + set_location(@1, @2); + $1->AsStmtList()->Stmts().append($2); + $1->UpdateLocationEndInfo(@2); + } + | + { $$ = new StmtList(); } + ; + +event: + TOK_ID '(' opt_expr_list ')' + { + set_location(@1, @4); + $$ = new EventExpr($1, $3); + } + ; + +case_list: + case_list case + { $1->append($2); } + | + { $$ = new case_list; } + ; + +case: + TOK_CASE expr_list ':' stmt_list + { $$ = new Case($2, $4); } + | + TOK_DEFAULT ':' stmt_list + { $$ = new Case(0, $3); } + ; + +for_head: + TOK_FOR '(' TOK_ID TOK_IN expr ')' + { + set_location(@1, @6); + + // This rule needs to be separate from the loop + // body so that we execute these actions - defining + // the local variable - prior to parsing the body, + // which might refer to the variable. + ID* loop_var = lookup_ID($3, current_module.c_str()); + + if ( loop_var ) + { + if ( loop_var->IsGlobal() ) + loop_var->Error("global used in for loop"); + } + + else + loop_var = install_ID($3, current_module.c_str(), + false, false); + + id_list* loop_vars = new id_list; + loop_vars->append(loop_var); + + $$ = new ForStmt(loop_vars, $5); + } + | + TOK_FOR '(' '[' local_id_list ']' TOK_IN expr ')' + { $$ = new ForStmt($4, $7); } + ; + +local_id_list: + local_id_list ',' local_id + { $1->append($3); } + | local_id + { + $$ = new id_list; + $$->append($1); + } + ; + +local_id: + TOK_ID + { + set_location(@1); + + $$ = lookup_ID($1, current_module.c_str()); + if ( $$ ) + { + if ( $$->IsGlobal() ) + $$->Error("already a global identifier"); + delete [] $1; + } + + else + { + $$ = install_ID($1, current_module.c_str(), + false, is_export); + } + } + ; + +global_id: + { resolving_global_ID = 1; } global_or_event_id + { $$ = $2; } + ; + +event_id: + { resolving_global_ID = 0; } global_or_event_id + { $$ = $2; } + ; + +global_or_event_id: + TOK_ID + { + set_location(@1); + + $$ = lookup_ID($1, current_module.c_str(), false); + if ( $$ ) + { + if ( ! $$->IsGlobal() ) + $$->Error("already a local identifier"); + + delete [] $1; + } + + else + { + const char* module_name = + resolving_global_ID ? + current_module.c_str() : 0; + + $$ = install_ID($1, module_name, + true, is_export); + } + } + ; + + +resolve_id: + TOK_ID + { + set_location(@1); + $$ = lookup_ID($1, current_module.c_str()); + if ( ! $$ ) + error("identifier not defined:", $1); + delete [] $1; + } + ; + +%% + +int yyerror(const char msg[]) + { + char* msgbuf = new char[strlen(msg) + strlen(last_tok) + 64]; + + if ( last_tok[0] == '\n' ) + sprintf(msgbuf, "%s, on previous line", msg); + else if ( last_tok[0] == '\0' ) + sprintf(msgbuf, "%s, at end of file", msg); + else + sprintf(msgbuf, "%s, at or near \"%s\"", msg, last_tok); + + error(msgbuf); + + return 0; + } diff --git a/src/version.c.in b/src/version.c.in new file mode 100644 index 0000000000..86c4b16f24 --- /dev/null +++ b/src/version.c.in @@ -0,0 +1 @@ +char version[] = "@VERSION@";