#!/bin/sh # Copyright 2021 alarig # # BSD-3-Clause licence # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. 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. # # 3. Neither the name of the copyright holder nor the names of its 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. # For debuggin purpose, uncomment the next line and `tail -F` the file. #exec 2> /tmp/check_bgp.log # This scipt works with bird2 only CONF_IGNORE_FILE="/usr/local/etc/nrpe-bird/ignore.cfg" usage() { printf "Usage:\n" printf "Must be run with user account able to use birdc/birdc6 or " printf "specify -s to use birdc with sudo.\n" printf "To ignore sessions, put one per line in ${CONF_IGNORE_FILE}.\n" } args=$(getopt hs $*) if [ $? -ne 0 ]; then usage exit 3 fi set -- $args while :; do case "$1" in -h) usage exit 0 shift;; -s) SUDO='sudo' shift;; --) shift; break;; esac done birdc="${SUDO} birdc" test_route_limit() { if [ "${ROUTE_HIT_IN}" != "" ]; then printf "${protocol_name} has hit import route " >> \ ${DIR}/CRITICAL.txt printf "limit\n" >> ${DIR}/CRITICAL.txt elif [ "${ROUTE_HIT_OUT}" != "" ]; then printf "${protocol_name} has hit export route " >> \ ${DIR}/CRITICAL.txt printf "limit\n" >> ${DIR}/CRITICAL.txt elif [ ${RATIO_IN} -gt 92 ]; then printf "${protocol_name} import route limit is " >> \ ${DIR}/WARNING.txt printf "over threshold\n" >> ${DIR}/WARNING.txt fi } test_exstart_neigh() { exstart_neighbors="$(${birdc} \ show ospf neighbors ${protocol_name} | grep -c ExStart)" if [ "${exstart_neighbors}" -gt 0 ]; then printf "${protocol_name} has " >> ${DIR}/WARNING.txt printf "${exstart_neighbors} ExStart " >> ${DIR}/WARNING.txt printf "neighbors\n" >> ${DIR}/WARNING.txt fi } # path expansion for birdc and sudo of FreeBSD PATH="$PATH:/usr/local/sbin/:/usr/local/bin/" DIR="$(mktemp -d '/tmp/nrpe-bird.XXXX')" #$birdc 'show protocols' | awk '$2 ~ "BGP" && $4 !~ "down" { print $0 }' > \ # ${DIR}/bgp_protocols_up.txt # The sed removes the first two lines (BIRD 2.0.2 ready and Name Proto blah) $birdc 'show protocols all' 2>${DIR}/bird-err | sed '1,2d;$d' | \ awk -v RS= -v DIR=$DIR '{print > (DIR "/" $1 ".txt")}' if [ "$(cat ${DIR}/bird-err)" != '' ]; then printf "ERROR: $(cat ${DIR}/bird-err)\n" rm -r ${DIR} exit 2 else rm ${DIR}/bird-err fi for protocol in $(cat ${CONF_IGNORE_FILE}); do rm "${DIR}/${protocol}.txt" done for protocol in $(find ${DIR} -type f); do protocol_name=$(echo ${protocol} | cut -d / -f 4 | cut -d . -f 1) STATE="$(head -n 1 ${protocol} | awk '{ print $6 }')" ROUTE_LIMIT_IN="$(awk '/Import limit/ { print $3 }' ${protocol})" ROUTES_IMPORTED="$(grep 'Routes:' ${protocol} | \ sed -Ee '/imported/{ s/^.* ([0-9]+) imported.*$/\1/; p;}' -e d)" ROUTE_HIT_IN="$(grep -E 'Receive limit:.*HIT' ${protocol})" if [ -z ${ROUTE_LIMIT_IN} ]; then # There is no import limit, so no ratio either RATIO_IN=0 else RATIO_IN=$(echo "(${ROUTES_IMPORTED}*100)/${ROUTE_LIMIT_IN}" \ | bc) fi ROUTE_HIT_OUT="$(grep -E 'Export limit:.*HIT' ${protocol})" # Plugin return codes: # https://nagios-plugins.org/doc/guidelines.html#AEN78 case ${STATE} in # BGP # Session states: # https://gitlab.labs.nic.cz/labs/bird/blob/master/proto/bgp/bgp.h#L601 Established | Passive) test_route_limit ;; OpenSent | OpenConfirm) printf "${protocol_name} is in ${STATE} state\n" >> \ ${DIR}/WARNING.txt ;; Idle | Connect | Active) printf "${protocol_name} is in ${STATE} state\n" \ >> ${DIR}/CRITICAL.txt ;; # OSPF # https://gitlab.labs.nic.cz/labs/bird/blob/master/proto/ospf/ospf.c#L532 Running) test_route_limit test_exstart_neigh ;; Alone) printf "${protocol_name} is in ${STATE} state\n" >> \ ${DIR}/WARNING.txt ;; # Or what *) if [ -z ${STATE} ]; then printf "Empty state for ${protocol_name}\n" \ >> ${DIR}/UNKNOWN.txt else printf "Unknown state ${STATE} for " >> \ ${DIR}/UNKNOWN.txt printf "${protocol_name}\n" >> ${DIR}/UNKNOWN.txt fi ;; esac done if [ -f ${DIR}/CRITICAL.txt ]; then printf "CRITICAL: $(cat ${DIR}/CRITICAL.txt)\n" rm -r ${DIR} exit 2 elif [ -f ${DIR}/WARNING.txt ]; then printf "WARNING: $(cat ${DIR}/WARNING.txt)\n" rm -r ${DIR} exit 1 elif [ -f ${DIR}/UNKNOWN.txt ]; then printf "UNKNOWN: $(cat ${DIR}/UNKNOWN.txt)\n" rm -r ${DIR} exit 3 else printf "OK: This is fine\n" rm -r ${DIR} exit 0 fi