#!/bin/bash -e

#################################################################################################
#
# Purpose:
#
# Takes parameters from the snmpwalk api and starts an snmpwalk job using those parameters
#
# Author: Justin Simon
#
#################################################################################################

# Default values
DEVICE_ADDRESS=""
DEVICE_PORT="161"
SNMP_VERSION="2c"
SNMP_COMMUNITY="public"
OID_SCAN_OPTIONS=""
MIB_SCAN_OPTIONS=""
TIMEOUT="15"
OUTPUT_DIR="/usr/local/nagiosxi/tmp/"

# Parse arguments
for ARG in "$@"; do
    case $ARG in
        --job_name=*)
            JOB_NAME="${ARG#*=}"
            ;;
        --device_address=*)
            DEVICE_ADDRESS="${ARG#*=}"
            ;;
        --device_port=*)
            DEVICE_PORT="${ARG#*=}"
            ;;
        --allow_non_sequential_oids=*)
            ALLOW_NON_SEQUENTIAL_OIDS="${ARG#*=}"
            ;;
        --force_numeric_oid_indexes=*)
            FORCE_NUMERIC_OID_INDICES="${ARG#*=}"
            ;;
        --snmp_version=*)
            SNMP_VERSION="${ARG#*=}"
            ;;
        --snmp_community=*)
            SNMP_COMMUNITY="${ARG#*=}"
            ;;
        --oid_scan_options=*)
            OID_SCAN_OPTIONS="${ARG#*=}"
            ;;
        --timeout=*)
            TIMEOUT="${ARG#*=}"
            ;;
        --max_results=*)
            MAX_RESULTS="${ARG#*=}"
            ;;
        --output_dir=*)
            OUTPUT_DIR="${ARG#*=}"
            ;;
        --mib_scan_options=*)
            MIB_SCAN_OPTIONS="${ARG#*=}"
            ;;
        --v3_security_level=*)
            SECURITY_LEVEL="${ARG#*=}"
            ;;
        --v3_username=*)
            USERNAME="${ARG#*=}"
            ;;
        --v3_auth_password=*)
            AUTH_PASSWORD="${ARG#*=}"
            ;;
        --v3_auth_protocol=*)
            AUTH_PROTOCOL="${ARG#*=}"
            ;;
        --v3_privacy_password=*)
            PRIVACY_PASSWORD="${ARG#*=}"
            ;;
        --v3_privacy_protocol=*)
            PRIVACY_PROTOCOL="${ARG#*=}"
            ;;
        --verify-only)
            VERIFY_ONLY="true"
            ;;
        *)
            echo "Unknown option: $ARG"
            exit 1
            ;;
    esac
done

# Check required parameters
if [[ -z "$DEVICE_ADDRESS" ]]; then
    echo "Error: --device_address is required"
    exit 1
fi

if [[ "$ALLOW_NON_SEQUENTIAL_OIDS" == "true" ]]; then
    OID_SCAN_OPTIONS="$OID_SCAN_OPTIONS -Cc"
fi

if [[ "$FORCE_NUMERIC_OID_INDICES" == "true" ]]; then
    OID_SCAN_OPTIONS="$OID_SCAN_OPTIONS -Ob"
fi

# Remove symbolic labels from enumerated values (we want "1" not "active(1)" for INTEGER types, etc.)
OID_SCAN_OPTIONS="$OID_SCAN_OPTIONS -Oe"

# Generate output file path
TIMESTAMP=$(date +%s)
OUTPUT_FILE="${OUTPUT_DIR}/snmpwalk_${DEVICE_ADDRESS}_${TIMESTAMP}.log"
PID_FILE="${OUTPUT_DIR}/snmpwalk_${DEVICE_ADDRESS}_${TIMESTAMP}.pid"

# Build SNMPWALK command based on SNMP version
if [[ "$SNMP_VERSION" == "3" ]]; then
    SNMPWALK_CMD="snmpwalk -v 3 -l $SECURITY_LEVEL -u $USERNAME"

    if [[ "$SECURITY_LEVEL" == "authNoPriv" || "$SECURITY_LEVEL" == "authPriv" ]]; then
        SNMPWALK_CMD="$SNMPWALK_CMD -a $AUTH_PROTOCOL -A $AUTH_PASSWORD"
    fi

    if [[ "$SECURITY_LEVEL" == "authPriv" ]]; then
        SNMPWALK_CMD="$SNMPWALK_CMD -x $PRIVACY_PROTOCOL -X $PRIVACY_PASSWORD"
    fi

    SNMPWALK_CMD="$SNMPWALK_CMD -t $TIMEOUT -r 1 $DEVICE_ADDRESS:$DEVICE_PORT $OID_SCAN_OPTIONS"
else
    # SNMPv1 or v2c
    SNMPWALK_CMD="snmpwalk -v $SNMP_VERSION -c $SNMP_COMMUNITY -t $TIMEOUT -r 1 $DEVICE_ADDRESS:$DEVICE_PORT $OID_SCAN_OPTIONS"
fi

# Sanitize passwords in scan output
# This is a good idea but for now we're getting the community string and passwword value for this file, so probably need to leave it unredacted for now
# SANITIZED_CMD=$(echo "$SNMPWALK_CMD" | \
#   sed -E \
#     -e 's/(-c[[:space:]]+)[^[:space:]]+/\1[REDACTED]/g' \
#     -e 's/(-A[[:space:]]+)[^[:space:]]+/\1[REDACTED]/g' \
#     -e 's/(-X[[:space:]]+)[^[:space:]]+/\1[REDACTED]/g'
# )

# Test SNMP connectivity first
TEST_OID="iso.3.6.1.2.1.1.1.0" # Consistent with other wizards/tests

if [[ "$SNMP_VERSION" == "3" ]]; then
    TEST_CMD="snmpget -v 3 -l $SECURITY_LEVEL -u $USERNAME"
    
    if [[ "$SECURITY_LEVEL" == "authNoPriv" || "$SECURITY_LEVEL" == "authPriv" ]]; then
        TEST_CMD="$TEST_CMD -a $AUTH_PROTOCOL -A $AUTH_PASSWORD"
    fi
    
    if [[ "$SECURITY_LEVEL" == "authPriv" ]]; then
        TEST_CMD="$TEST_CMD -x $PRIVACY_PROTOCOL -X $PRIVACY_PASSWORD"
    fi
    
    TEST_CMD="$TEST_CMD -t 5 -r 1 $DEVICE_ADDRESS:$DEVICE_PORT $TEST_OID"
else
    # SNMPv1 or v2c
    TEST_CMD="snmpget -v $SNMP_VERSION -c $SNMP_COMMUNITY -t 5 -r 1 $DEVICE_ADDRESS:$DEVICE_PORT $TEST_OID"
fi

# Run test and capture output
TEST_OUTPUT=$($TEST_CMD 2>&1)
TEST_EXIT_CODE=$?

if [[ $TEST_EXIT_CODE -ne 0 ]]; then
    echo "$TEST_OUTPUT"
    exit 1
fi

if [[ "$VERIFY_ONLY" == "true" ]]; then
    exit 0
fi

echo "SNMP connectivity test passed. Starting SNMP walk..."


# Launch command in background and limit output
(
    # Build job prefix if JOB_NAME is set; escape single quotes for use inside single-quoted string
    if [ -n "$JOB_NAME" ]; then
        JOB_NAME_ESCAPED="${JOB_NAME//\'/\\\'}"
        JOB_PREFIX="Running job '${JOB_NAME_ESCAPED}': "
    else
        JOB_PREFIX="Running: "
    fi

    if [ -n "$MAX_RESULTS" ] && [ "$MAX_RESULTS" -gt 0 ]; then
        echo "${JOB_PREFIX}${SNMPWALK_CMD} with Max Results set to: $MAX_RESULTS"
        $SNMPWALK_CMD 2>&1 | head -n "$MAX_RESULTS"
    else
        echo "${JOB_PREFIX}${SNMPWALK_CMD}"
        $SNMPWALK_CMD 2>&1
    fi
) > "$OUTPUT_FILE" &


# Save the PID
PID=$!
echo "$PID" > "$PID_FILE"

echo "SNMP walk job started asynchronously."
echo "PID: $PID"
echo "Output will be written to: $OUTPUT_FILE"
echo "PID file: $PID_FILE"

# Detach cleanup watcher in background
nohup bash -c "
    while kill -0 $PID 2>/dev/null; do sleep 1; done
    rm -f \"$PID_FILE\"
" >/dev/null 2>&1 & disown

exit 0
