zeek/scripts/bro.rc.in

1098 lines
29 KiB
Bash
Executable file

#!/bin/sh
# $Id: bro.rc.in 4620 2007-07-09 21:23:52Z vern $
#
# Start script for running Bro.
#
# This will run one instance of Bro. If there is a need to run more than one
# instance at a time then copy this script to a new file and change the name
# to something else.
#
# chkconfig: - 57 30
#
# description: Bro is a highly customizable intrusion detection system \
# developed at Lawrence Berkeley National Labs.
# processname: bro
# pidfile: /var/run/bro-lite/pid
# config: /etc/sysconfig/bro-lite
#
# Written by Roger Winslow rwinslow@lbl.gov
# Variables which are exported on a startup and needed by Bro
# This variable used to be called BRO_ID
# BRO_LOG_SUFFIX
# For tasks to complete before and after Bro starts please edit the following
# scripts to suit your needs. For those of you familiar with dhclient this
# uses the same idea.
# Before Bro starts $BROHOME/etc/bro.rc-hooks.sh
# See the bottom of this script for an explanation of how this all works.
# I'll try my best to be clear....
prog="bro.rc"
RETVAL=0
# picked up from configure at install time
BROHOME="@prefix@"
export BROHOME
# Set the environment.
source_config="${BROHOME}/etc/bro.cfg"
# Location of bro-hooks.sh script
bro_hooks="${BROHOME}/etc/bro.rc-hooks.sh"
# Set the full path to this script as called
if [ `echo ${0} | grep -E "^/"` ]; then
this_script="${0}"
else
this_script="`pwd`/${0}"
fi
# Set the args as passed to this script
cur_args="$*"
# Load the source config
if ! [ -f ${source_config} ] || ! . "${source_config}"; then
echo "${prog}: Unable to load the source config file at ${source_config}" >&2
exit 1
fi
# Source the bro_hooks script if exists and readable
if ! [ -f "${bro_hooks}" ] || ! . "${bro_hooks}"; then
echo "${prog}: Unable to source the bro.rc-hooks.sh script at ${bro_hooks}" >&2
fi
syslog_cmd="logger"
run_dir="${BRO_RUNTIME_DIR}"
pidfile="${run_dir}/pid"
start_time_file="${run_dir}/start_time"
active_log_file="${BROLOGS}/active_log"
autorestart_file="${run_dir}/autorestart"
alternate_user_id=${BRO_USER_ID}
renice_checkpoint_level=15
time_between_restarts=2
minimum_mortality_time=60
# Setting DEBUG to 1 will prevent the following
# forking of the Bro process into the background
# any autorestart features
# any bro.rc-hooks.sh functions
# writing of data to $BRO_RUNTIME_DIR
# redirection of STDERR and STDOUT to the info file
DEBUG=0
# Export a few items that Bro needs to run
export BROLOGS
export BROPATH
export BROHOME
export PATH="${BROHOME}/bro/bin:${BROHOME}/bro/scripts:/usr/local/bin:/usr/local/sbin:${PATH}"
# Make sure that the $BRO_RUNTIME_DIR exists and is writtable
if [ ! -d "${BRO_RUNTIME_DIR}" ]; then
mkdir "${BRO_RUNTIME_DIR}"
if [ "$?" != "0" ]; then
echo "${prog}: Failed to create the runtime directory at ${BRO_RUNTIME_DIR}" >&2
echo "${prog}: Unable to continue" >&2
exit 1
fi
if [ "${alternate_user_id}x" != "x" ] && [ "${alternate_user_id}" != "${USER}" ]; then
chown ${alternate_user_id} "${BRO_RUNTIME_DIR}"
if [ "$?" != "0" ]; then
echo "${prog}: Failed to change owner on runtime directory ${BRO_RUNTIME_DIR}" >&2
echo "${prog}: Unable to continue" >&2
exit 1
fi
fi
fi
start() {
# Make a few sanity checks
# Make sure the BROLOGS directory is writeable
if [ ! -d ${BROLOGS} ] || [ ! -w ${BROLOGS} ]; then
echo "${prog}: BROLOGS directory at ${BROLOGS} is not writable." >&2
echo "${prog}: Unable to continue" >&2
exit 1
fi
# Check to make sure that the Bro executable is at least --x
if [ ! -x "${BRO}" ]; then
echo "${prog}: Unable to execute the bro binary at ${BRO}" >&2
echo "${prog}: Unable to continue" >&2
exit 1
fi
# Check to make sure that bro is not already running
local pid
if [ -f "${pidfile}" ]; then
pid=`cat "${pidfile}"`
if [ "${pid}x" = "x" ]; then
cleanup
else
local _is_running
pidisrunning ${pid} "${BRO}"
_is_running=$?
if [ "${_is_running}" != "0" ]; then
cleanup
else
echo "${prog}: already running with a pid of ${pid}"
# errno code for EEXIST = 17
return 17
fi
fi
fi
# Check to make sure that a start policy has been specified
if [ "${BRO_START_POLICY}x" = "x" ]; then
echo "${prog}: No start policy file specified." >&2
echo "${prog}: Unable to continue" >&2
return 1
fi
# Change to the BROLOGS directory
local _did_cd
cd "${BROLOGS}"
_did_cd=$?
if [ "${_did_cd}" != "0" ]; then
echo "${prog}: Failed to change to BROLOGS directory at ${BROLOGS}" >&2
echo "${prog}: Unable to continue" >&2
return 1
fi
# Start Bro
local _start_result
echo -n "${prog}: Starting "
# What type of start should be performed
if [ "${DEBUG}" = '1' ]; then
startbro
return
elif [ "${AUTO_RESTART}" = 't' ]; then
autorestart &
else
startbro &
fi
sleep 1
_start_result=$?
# Check the return code to see if it started
local _failed_check_count
_failed_check_count=0
if [ "${_start_result}" = '0' ] || [ "${_start_result}x" = 'x' ]; then
local _loop_count
_loop_count=0
while [ ${_loop_count} -lt 12 ]
do
_loop_count=$(( ${_loop_count} + 1 ))
echo -n '.'
# Sometimes the result from the fork takes a few seconds
# Check if was not set yet
if [ "${_start_result}x" = 'x' ]; then
_start_result=$?
if [ "${_start_result}x" != 'x' ] && [ "${_start_result}" != '0' ]; then
break
fi
else
# Use the status function to see if Bro is still up
local _status_result
status 2>/dev/null >/dev/null
_status_result=$?
if [ "${_status_result}" != '0' ] || [ "${_start_result}" != '0' ]; then
_failed_check_count=$(( ${_failed_check_count} + 1 ))
if [ ${_failed_check_count} -gt 11 ]; then
_start_result=1
break
fi
fi
fi
sleep 1
done
fi
if [ "${_start_result}" = '0' ]; then
echo ". SUCCESS"
else
echo ". FAILED"
fi
return ${_start_result}
}
startbro() {
local cur_date
local _already_running
local trace_file
local cmd_opts
local basic_cmd_opts
cur_date=`date +%y-%m-%d_%H.%M.%S`
BRO_LOG_SUFFIX="${BRO_HOSTNAME}.${cur_date}"
export BRO_LOG_SUFFIX
trace_file="${BROLOGS}/trace.${BRO_LOG_SUFFIX}"
info_log="${BROLOGS}/info.${BRO_LOG_SUFFIX}"
cmd_opts="${BRO_OPTS}"
# Check if Bro is already running
status 2>/dev/null >/dev/null
_already_running=$?
if [ "${_already_running}" = '0' ]; then
return 17
fi
# Build the command line.
# Should a trace file be created
if [ "${BRO_CREATE_TRACE_FILE}" = 'YES' ] || [ "${BRO_CREATE_TRACE_FILE}" = 'yes' ]; then
cmd_opts="${cmd_opts} -w ${trace_file}"
fi
# If a specific interface to capture on is specified then add it in
# This is a space delimited list
if [ "${BRO_CAPTURE_INTERFACE}x" != 'x' ]; then
for _intf in ${BRO_CAPTURE_INTERFACE}
do
cmd_opts="${cmd_opts} -i ${_intf}"
done
fi
# Append the Bro policy which to start
if [ "${BRO_START_POLICY}x" != 'x' ]; then
cmd_opts="${cmd_opts} ${BRO_START_POLICY}"
else
echo "${prog}: No start policy file specified." >&2
fi
local new_pid
local bro_result
cd "${BROLOGS}"
# Check whether DEBUG is set. If so then keep Bro attached to the shell
# and don't fork.
if [ "${DEBUG}" != '0' ]; then
"${BRO}" ${cmd_opts}
return
# Run bro. Redirect STDERR and STDOUT to $info_log
else
"${BRO}" ${cmd_opts} 2>>"${info_log}" >>"${info_log}" &
fi
bro_result=$?
new_pid=$!
# Check the exit code returned by Bro
if [ "${bro_result}" = '0' ] || [ -z "${bro_result}" ]; then
local _loop_count
_loop_count=0
while [ ${_loop_count} -lt 10 ]
do
_loop_count=$(( ${_loop_count} + 1 ))
if [ -f "${info_log}" ]; then
if [ "`grep -E '^listening on' ${info_log}`x" != 'x' ]; then
break
fi
fi
# break now if the process returned a non-zero value
if [ "${bro_result}x" != 'x' ] && [ "${bro_result}" != '0' ]; then
break
fi
sleep 1
done
fi
# check to make sure that Bro actually started
if [ "${new_pid}x" = 'x' ] || [ "${bro_result}" != '0' ]; then
false
else
pidisrunning ${new_pid} "${BRO}"
_is_running=$?
if [ "${_is_running}" != '0' ]; then
bro_result=1
fi
fi
if [ "${bro_result}" != '0' ]; then
echo "${prog}: Failed to start Bro"
if [ -f "${info_log}" ] && [ -s "${info_log}" ]; then
cat "${info_log}"
ERROR_MESSAGE=`cat "${info_log}"`
else
ERROR_MESSAGE='Unknown error, no messages recieved on STDERR or STDOUT'
fi
# Call the post_start_hook function
LOG_SUFFIX="${BRO_LOG_SUFFIX}"
EXIT_CODE=${bro_result}
"${syslog_cmd}" -t "${prog}" "Bro has failed to start. ${ERROR_MESSAGE}"
post_start_hook
return ${bro_result}
else
"${syslog_cmd}" -t "${prog}" "Bro process (${new_pid}) has started"
fi
# Write the pid out to file
echo ${new_pid} > "${pidfile}"
# Write the active log suffix out to file
echo "${BRO_LOG_SUFFIX}" > "${active_log_file}"
# Write the start date out to file
local _start_time
_start_time=`date`
echo "${_start_time}" > "${start_time_file}"
# Write the auto-restart status out to file
if [ "${AUTO_RESTART}" = 't' ]; then
echo "ON" > "${autorestart_file}"
else
echo "OFF" > "${autorestart_file}"
fi
echo "Bro Version: `\"${BRO}\" -v 2>&1 | awk ' { print $3 } '`" >> "${info_log}"
echo "Started with the following command line options: ${cmd_opts}" >> "${info_log}"
# Get the BPF capture filter
local _print_filter
local _print_filter_result
# Strip out the trace file parameter if it exists
basic_cmd_opts=`removetraceopt "${cmd_opts}"`
_print_filter=`capturefilter "${basic_cmd_opts}"`
_print_filter_result=$?
if [ "${_print_filter_result}" = '0' ]; then
echo "Capture filter: ${_print_filter}" >> "${info_log}"
else
echo 'Capture filter: <not available>' >> "${info_log}"
fi
# Call the post_start_hook function
LOG_SUFFIX="${BRO_LOG_SUFFIX}"
PID=${new_pid}
EXIT_CODE=""
ERROR_MESSAGE=""
START_TIME="${_start_time}"
END_TIME=""
post_start_hook
local _exitwatch_result
exitwatch ${new_pid}
_exitwatch_result=$?
return ${_exitwatch_result}
}
autorestart() {
local _cur_restart_count
local _max_restart_count
local _called_from # name of function that called autorestart if any
local _failed_first_start
local _start_res
local _minimum_life
_minimum_life=$(( `epochtime` + ${minimum_mortality_time} ))
_called_from="${1}"
_cur_restart_count=0
_max_restart_count=${BRO_MAX_RESTART_ATTEMPTS}
# If _max_restart_count is not defined or is less than 1 then
# this equats to no restart limit.
if [ "${_max_restart_count}x" = 'x' ] || [ ${_max_restart_count} -lt '1' ]; then
_cur_restart_count=-2
_max_restart_count=-1
fi
# loop and restart bro until told to exit
while [ ${_cur_restart_count} -lt ${_max_restart_count} ]
do
local _cur_epoch_time
# startbro will block until Bro exits
startbro
_start_res=$?
_cur_epoch_time="`epochtime`"
if [ "${_start_res}" = '0' ]; then
# Bro exited normally due to a planned stop
break
elif [ "${_start_res}" = '17' ]; then
echo "${prog}: Unable to begin autorestart. Stop the running instance of Bro first." >&2
echo "${prog}: Unable to continue" >&2
break
elif [ ${_cur_epoch_time} -lt ${_minimum_life} ]; then
_failed_first_start=1
break
fi
# If _max_restart_count is greater than 0 increment _cur_restart_count
# otherwise don't because no restart limit has been set.
if [ ${_max_restart_count} -gt '0' ]; then
_cur_restart_count=$(( ${_cur_restart_count} + 1 ))
fi
sleep ${time_between_restarts}
"${syslog_cmd}" -t "${prog}" "Autorestarting Bro due to unexpected exit"
done
# Check why the loop exited
if ! [ ${_cur_restart_count} -lt ${_max_restart_count} ]; then
# Stop Bro, this will force a cleanup of the run-time directory
stopbro 2> /dev/null 1> /dev/null
EXIT_CODE=${_start_res}
ERROR_MESSAGE="Exceeded maximum autorestart count of ${BRO_MAX_RESTART_ATTEMPTS}. No further attempts will be made to restart Bro"
END_TIME=`date`
# Call the post_exit_hook to report the error
post_exit_hook
return 1
elif [ "${_failed_first_start}" = '1' ]; then
# Bro failed on the very first start and this was not during a checkpoint.
# No further restarts will be attempted.
"${syslog_cmd}" -t "${prog}" "Bro process failed on first start attempt. No further restart attempts will be made."
EXIT_CODE=""
ERROR_MESSAGE="Failed on first start attempt. No further restart attempts will be made."
# Call the post_exit_hook to report the error
post_exit_hook
return ${_start_res}
fi
return 0
}
stopbro() {
# Check to see if bro is running
local _pid
local _bro_is_running
local _status_result
status 2>/dev/null >/dev/null
_status_result=$?
if [ "${_status_result}" = '0' ]; then
# try and stop it
local _kill_result
echo -n "${prog}: Stopping "
_pid=`cat "${pidfile}"`
_bro_is_running="t"
cleanup
for _i in 1 2; do
echo -n '.'
sleep 1
done
kill -TERM ${_pid}
_kill_result=$?
if [ "${_kill_result}" = "0" ]; then
true
else
echo "${prog}: Failed to stop process with pid ${_pid}"
return 1
fi
else
_bro_is_running="f"
if [ -f "${pidfile}" ]; then
cleanup
fi
fi
if [ "${_bro_is_running}" = "f" ]; then
echo "${prog}: No running process to stop"
return 0
fi
# Now see if the process is still hanging around.
# Bro can stick around a long time as it writes out logs and writes it's
# state info to disk
local _is_dead
for _i in 1 2 3 4 5 6 7 8 9 10; do
_is_dead=""
pidisrunning ${_pid} "${BRO}"
_is_dead=$?
echo -n "."
if [ "${_is_dead}" != "0" ]; then
break
fi
sleep 1
done
if [ "${_is_dead}" != "0" ]; then
echo " SUCCESS !"
else
echo "${prog}: Process (${_pid}) has still not exited."
echo "${prog}: If it has not exited after ${BRO_MAX_SHUTDOWN_TIME} seconds from now it will be forced to exit."
# Create a backgound process to watch the terminated Bro
# If the process still exists after the BRO_MAX_SHUTDOWN_TIME
# then send it a SIG_KILL
stopwatch ${_pid} "${BRO}" &
fi
return 0
}
checkpoint() {
# Check to make sure bro is already running
local _old_pid=""
local _old_bro_running
local _status_result
echo "${prog}: Beginning the checkpoint process"
status 2>/dev/null >/dev/null
_status_result=$?
if [ "${_status_result}" = '0' ]; then
_old_pid=`cat "${pidfile}"`
_old_bro_running="t"
else
_old_bro_running="f"
fi
if [ "${_old_bro_running}" = "f" ]; then
cleanup
echo "${prog}: No current instance of Bro is running."
return 1
fi
echo "${prog}: Starting a new Bro instance."
if [ "${_old_bro_running}" = "t" ]; then
echo "${prog}: Will wait for ${BRO_CHECKPOINT_OVERLAP_TIME} seconds before stopping the old Bro instance."
fi
# start a new Bro
"${syslog_cmd}" -t "${prog}" "Starting the checkpoint process (${_old_pid})"
cleanup
${this_script} start > /dev/null &
# Create a background process to stop the old Bro process if
# it is still running
if [ "${_old_bro_running}" = "t" ]; then
{
# Renice the old process so it doesn't compete with the new active Bro
renice ${renice_checkpoint_level} ${_old_pid} 2> /dev/null 1> /dev/null
# Sleep for BRO_CHECKPOINT_OVERLAP_TIME
sleep ${BRO_CHECKPOINT_OVERLAP_TIME}
# kill the old bro process
kill -TERM ${_old_pid}
# call the stopwatch function to make sure the old bro process exits
# before BRO_MAX_SHUTDOWN_TIME
stopwatch ${_old_pid} "${BRO}"
"${syslog_cmd}" -t "${prog}" "Checkpoint process complete. Bro process (${_old_pid}) is done"
} &
fi
return 0
}
status() {
local _pid
local _ret_val
if [ -f "${pidfile}" ] && [ -f "${start_time_file}" ] && [ "${active_log_file}" ]; then
_pid=`cat "${pidfile}" | awk '{ print $1 }'`
pidisrunning ${_pid}
_ret_val=$?
if [ "${_ret_val}" = "0" ]; then
true
else
echo "${prog}: Bro is not running"
return 1
fi
else
echo "${prog}: Bro is not running"
return 1
fi
local _start_time
local _log_suffix
local _bro_ver
local _autorestart_status
_start_time=`cat "${start_time_file}"`
_log_suffix=`activelogsuffix`
_bro_ver=`"${BRO}" -v 2>&1 | awk ' { print $3 } '`
_autorestart_status=`cat "${autorestart_file}"`
echo "Bro is running (pid: ${_pid})"
echo "Autorestart: ${_autorestart_status}"
echo "Running since: ${_start_time}"
echo "Bro Version: ${_bro_ver}"
echo "Active log suffix: ${_log_suffix}"
return 0
}
activelogsuffix() {
local _log_suffix
if [ -f "${active_log_file}" ] && [ -r "${active_log_file}" ]; then
# ok file exists
_log_suffix=`cat "${active_log_file}"`
echo -n "${_log_suffix}"
else
return 1
fi
return 0
}
exitwatch() {
# pid number to wait for
PID=${1}
if [ -z ${PID} ]; then
echo "${prog}: No pid number passed to function exitwatch" > 2
echo "${prog}: Unable to continue" > 2
exit 1
fi
# trap some signals
# Ignore HUP, QUIT, INT signals
trap '' SIGHUP SIGINT SIGQUIT
# Call stop if a TERM signal is sent to this ($$) process
trap 'stopbro 2>/dev/null >/dev/null; true' SIGTERM
wait ${PID} 2> /dev/null
EXIT_CODE=$?
END_TIME=`date`
# Currently Bro does not always exit with the right exit codes
# Need to figure out if something besides 0 really happened
if [ "${EXIT_CODE}x" = 'x' ]; then
# Something evil happened!
EXIT_CODE=1
false
# The following exit codes are expected for a successful exit:
# 0, 130, 145
# 143 (SIGTERM) and 130 (SIGINT) are returned when wait is interrupted by
# a trapped signal.
elif [ "${EXIT_CODE}" = '0' ] || \
[ "${EXIT_CODE}" = '143' ] || \
[ "${EXIT_CODE}" = '130' ]; then
if ! [ -f "${pidfile}" ]; then
# A normal exit occurred as the pid file has been cleaned up
EXIT_CODE=0
true
else
check_pid=`cat "${pidfile}"`
if [ "${check_pid}" != "${PID}" ]; then
# The PID has changed which means either a restart was forced
# or a checkpoint has occurred. In either case it is
# likely that Bro exited correctly
true
else
# Something went wrong with Bro because it exited before the
# temporal files were cleaned up
EXIT_CODE=1
cleanup
false
fi
fi
elif [ ! -f "${pidfile}" ] && [ ! -f "${start_time_file}" ]; then
# Bro exited with a non-zero value but the exit was planned.
# Log the an error message but return a zero exit status as this
# was a planned exit.
"${syslog_cmd}" -t "${prog}" "Bro process (${PID}) returned a non-zero exit status but the exit was planned."
EXIT_CODE=0
else
# An unexpected exit code was returned by Bro
false
fi
# Set the ERROR_MESSAGE to something useful if there was an error
if [ "${EXIT_CODE}" != '0' ]; then
if [ -f "${info_log}" ] && [ -s "${info_log}" ]; then
ERROR_MESSAGE=`tail -2 "${info_log}"`
else
ERROR_MESSAGE="Unknown error occurred"
fi
"${syslog_cmd}" -t "${prog}" "Bro process (${PID}) exited with a code of ${EXIT_CODE}"
else
"${syslog_cmd}" -t "${prog}" "Bro process (${PID}) stopped"
fi
# Call the post_exit_hook function
post_exit_hook
# renamed logfiles now that file writing is done.
# turned off till sc04 is over
# rename_logfiles "${BRO_LOG_SUFFIX}"
return ${EXIT_CODE}
}
stopwatch() {
# This function is used to run in the background and watch the pid
# and command line as returned by ps. This function should be
# forked off as a background process to monitor a terminating Bro
# process to make sure that it ends by BRO_MAX_SHUTDOWN_TIME
local _pid
local _cmd_line
_pid=${1}
_cmd_line="${2}"
# Make sure that _pid has a value
if [ -z ${_pid} ]; then
_pid=`cat "${pidfile}"`
if [ -z ${_pid} ]; then
echo "${prog}: Unable to find a process number to monitor for stopwatch" >&2
fi
echo "First argument passed to function stopwatch must be a PID greater than zero." >&2
return 1
fi
# Make sure that _pid has a value larger than 0
if [ "${_pid}" -lt 1 ]; then
echo "First argument passed to function stopwatch must be a PID greater than zero." >&2
return 1
fi
# Make sure that _cmd_line has a value
if [ -z ${_cmd_line} ]; then
echo "Second option passed to function stopwatch must be the program name as" >&2
echo "specified on the command line when first started." >&2
fi
local _cur_wait
local _max_wait
local _sleep_time
_cur_wait=0
_max_wait=${BRO_MAX_SHUTDOWN_TIME}
_sleep_time=10
while [ "${_cur_wait}" -lt "${_max_wait}" ]
do
local _res
pidisrunning ${_pid} "${_cmd_line}"
local _ret_val=$?
if [ "${_ret_val}" != "0" ]; then
break
fi
_cur_wait=$(( ${_cur_wait} + ${_sleep_time} ))
sleep ${_sleep_time}
done
# Check if the process died on it's own
if [ "${_cur_wait}" -ge "${_max_wait}" ]; then
# Nope, didn't exit on it's own
kill -KILL ${_pid}
"${syslog_cmd}" -t "${prog}" "Bro process (${_pid}) exceeded the maximum shutdown time and was forcibly terminated"
fi
return 0
}
runasnonroot() {
# Check on whether to start as the current user or a different user
#
# Check if the alternate user has been specified
if [ "${alternate_user_id}x" != "x" ]; then
# Check if the current username is the same as that in $alternate_user_id
if [ "${USER}" = "${alternate_user_id}" ]; then
# The alternate is the same as the current, no need to su
alternate_user_id=''
return 254
else
# Allow only users with root privelages to use su -
if [ -w /etc/passwd ]; then
echo "${prog}: Running as non-root user ${alternate_user_id}" >&2
su - ${alternate_user_id} -c "${this_script} ${cur_args} < /dev/null"
else
# Nope, no root privelage
alternate_user_id=''
echo "$prog: Must have root privileges in order to run as a non-root user" >&2
echo "FAILED!" >&2
return 1
fi
fi
else
# No alternate user specified
return 254
fi
return 0
}
pidisrunning() {
local _pid
local _cmd_line
local _running_pid
_pid=${1}
_cmd_line="${2}" # optional
if [ `uname | grep "CYGWIN"` ]; then
# cygwin ps command
if [ -z ${_cmd_line} ]; then
_running_pid=`ps -as | awk ' { print $1 } ' | grep ${_pid}`
else
_running_pid=`ps -as | grep "${_pid}.*${_cmd_line}"`
fi
else
# the rest of *NIX
_running_pid=`ps ax -o "pid,command" | grep "${_pid}.*${_cmd_line}" | grep -v "grep ${_pid}.*${_cmd_line}"`
fi
if [ "${_running_pid}x" = 'x' ]; then
return 1
else
return 0
fi
}
removetraceopt() {
local _cmd_opts
local _ret_string
local _sed_patt
_cmd_opts="${1}"
_sed_patt='/-w/ {
/-w *\"/ {
s/ -w *\"[^"]\{1,\}\" */ /
t
s/^-w *[^" ]\{1,\} */ /
}
t
/-w *[^ ]\{1,\}/ {
s/ -w *[^ ]\{1,\} */ /
t
s/^-w *[^ ]\{1,\} */ /
}
}'
_ret_string=`echo -n "${cmd_opts}" | sed "${_sed_patt}"`
echo -n "${_ret_string}"
return 0
}
capturefilter() {
local _cmd_opts
local _ret_string
local _dummy_dir
local _cur_log_suffix
_cmd_opts="${1}"
_cmd_opts="${_cmd_opts} print-filter.bro"
_dummy_dir="${BROLOGS}/.print-filter"
mkdir "${_dummy_dir}" 1>/dev/null 2>/dev/null
cd "${_dummy_dir}"
_ret_string=`"${BRO}" ${_cmd_opts} 2>/dev/null`
cd "${BROLOGS}"
rm -rf "${_dummy_dir}"
if [ "${_ret_string}x" = 'x' ]; then
return 1
else
echo "${_ret_string}"
return 0
fi
}
cleanup() {
rm -f "${pidfile}"
rm -f "${active_log_file}"
rm -f "${start_time_file}"
rm -f "${autorestart_file}"
return 0
}
epochtime() {
echo -n "`date +'%s'`"
}
# Need something more comprehensive but this does fine for now.
rename_logfiles() {
# rename the closed log file passed in as arg ${1} and add
# the stop time. The format of the files will now be:
# file.host.YY-MM-DD_HH.MM.SS-YY-MM-DD_HH.MM.SS, where the first date
# is the start time, and the end date is the time bro was shutdown
local _end_time
local _cur_log_suffix
# The start time log suffix is passed in as an argument
_cur_log_suffix="${1}"
# change directory to where we need to do our work
cd "${BROLOGS}"
# If _cur_log_suffix has no value then don't do anything
if [ "${_cur_log_suffix}x" = 'x' ]; then
#echo "No logs to rename"
return 1
fi
# format the end time once, and use for all the logs
_end_time=`date "+%y-%m-%d_%H.%M.%S"`
# grok out the logs to change, and change them, hope we have lots of disk space
filelist=`ls *.${_cur_log_suffix}`
for name in ${filelist}; do
#echo "Moving ${name} to ${name}-${_end_time}"
mv "${name}" "${name}-${_end_time}"
done
return 0
}
# See how we were called.
case "$1" in
status|--status)
status
;;
start|--start|autorestart|--autorestart|stop|--stop|stopwatch|--stopwatch|checkpoint|--checkpoint)
# Check on whether to run as non-root
runasnonroot
_run_non_root_res=$?
if [ "${_run_non_root_res}" = "0" ]; then
true
elif [ "${_run_non_root_res}" = "1" ]; then
false
else
# If it gets here then the script is either running as root or it has
# already done an su - to the non-root user.
case "$1" in
start|--start)
# One more command line option is available
second_opt="${2}"
# enable autorestart?
AUTO_RESTART="f"
if [ "${BRO_ENABLE_AUTORESTART}" = "YES" ] || \
[ "${BRO_ENABLE_AUTORESTART}" = "yes" ] || \
[ "${second_opt}" = "autorestart" ]; then
AUTO_RESTART="t"
fi
# An explicit noautorestart will always disable it
if [ "${second_opt}" = "noautorestart" ]; then
AUTO_RESTART="f"
fi
start
;;
startbro|--startbro)
startbro
;;
stop|--stop)
stopbro
;;
# stopwatch|--stopwatch)
# stopwatch ${2}
# ;;
checkpoint|--checkpoint)
checkpoint
esac
fi
;;
*)
echo "Usage: ${prog} {start|stop|checkpoint|status}"
echo "start has the additional option which can be used to disable/enable "
echo "autorestart: "
echo " start [no]autorestart"
echo ""
exit 1
esac
exit $?
# So how does this thing work and why is it always running when Bro is running?
# bro.rc is the init script which starts, stops, checkpoints, and monitors a
# running instance of Bro.
# bro.rc logs it's actions to syslog via the logger command.
# bro.rc offers users an interface into the starting and stopping of a Bro
# process via the file $BROHOME/etc/bro.rc-hooks.rc. This allows for
# actions to be sent to any custom monitoring or alerting programs the
# user may wish to use.
# There are four command line options available
# to the user. Each is covered below with an explanation.
# 1) start
# Start has two additional commands of autorestart and noautorestart which
# can be used to enable and disable the autorestart feature. This feature
# is also controlled by setting the variable BRO_ENABLE_AUTORESTART in
# to 'YES' or 'NO' bro.cfg. Any autorestart option given to start on the
# command line will override the bro.cfg setting in BRO_ENABLE_AUTORESTART.
#
# 'start' does just as it's name implies, it starts a new Bro process.
# When autorestart is enabled bro.rc will monitor the Bro process and
# restart it if it fails unexpectedly for any reason. Bro will be restarted
# a maximum count as set by BRO_MAX_RESTART_ATTEMPTS in bro.cfg. If the
# BRO_MAX_RESTART_ATTEMPTS count is exceeded then no further restart
# attempts will be made and the error will be sent to syslog.
#
# After Bro has started either successfully or unsuccessfully the function
# post_start_hook will be called. (see bro.rc-hooks.sh for more info).
#
# If start is called and Bro is already running this is an error and
# the script will return 1.
#
# If Bro starts successfully bro.rc will return 0.
#
# 2) stop
# Self explantory, stops a running Bro process. Stop will cleanup the
# temporal files such as pid, start_time, etc, send a SIGTERM to the
# running instance of Bro, and then if needed call another process to
# to watch the exiting process. If the process has not terminated by
# BRO_MAX_SHUTDOWN_TIME seconds then a SIGKILL will be sent to the process
# and a message will be sent to syslog.
#
# 3) checkpoint
# A checkpoint is where a new instance of Bro is started and then the old
# one is terminated. (see documentation on when and why this is done).
# Essentially what happens is that temporal files are cleaned up, a
# new instance of Bro is started, bro.rc thens waits
# BRO_CHECKPOINT_OVERLAP_TIME seconds before sending the old Bro process
# a SIGTERM. An exit code of 1 will be returned in the event checkpoint
# is called and there is no running Bro process.
#
# 4) status
# Used to check if Bro is running. Also outputs the Bro version, the start
# time, the current log suffix, and whether autorestart is enabled or not.
# If Bro is running the command will return 0 and if Bro is not running the
# command will return 1.
#
# The detection of when Bro exits is done through the use of the shell
# builtin 'wait'. The function exitwatch will wait on the Bro child
# pif until it exits. A few tests are run after Bro returns to determine
# If the exit was expected or unexpected. An unexpected exit is anytime
# Bro exits or terminates outside the control of bro.rc. After the Bro
# process returns and before bro.rc exits the post_exit_hook will be called.
#
# bro.rc traps SIGTERM and ignores SIGHUP. If SIGTERM is sent to the
# bro.rc process this will also cause bro.rc to stop the running Bro process
# it monitors as well. This is to provide proper behavior in the event of
# a system reboot or halt.