#!/usr/bin/env bash
#
# onx-firewall-trusted-add — Master allowlist'e IPv4/IPv6/CIDR ekle.
#
# Bu set'teki adresler tüm threat/country/cphulk drop kurallarından önce eşleşir
# (priority -100 chain) — yani önceliklidir.
#
# Input (stdin JSON): {"ip": "1.2.3.4" | "10.0.0.0/8" | "2001:db8::1" | "2001:db8::/32"}
# Output: {"ok":true,"ip":"...","set":"onox-trusted|onox-trusted-v6","family":"v4|v6"}
#
# Exit codes: 0=ok, 1=bad input, 4=nft fail

set -euo pipefail

input="$(cat)"
ip="$(echo "$input" | jq -r '.ip // empty')"

if [[ -z "$ip" ]]; then
    jq -nc '{ok:false,error:"ip required"}' >&2
    exit 1
fi

# ── Detect family + validate ──────────────────────────────────────────────
family=""
addr_part="${ip%/*}"

if [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}(/(3[0-2]|[12]?[0-9]))?$ ]]; then
    # IPv4 check: her octet 0-255
    IFS='.' read -r o1 o2 o3 o4 <<< "$addr_part"
    if (( o1 > 255 || o2 > 255 || o3 > 255 || o4 > 255 )); then
        jq -nc --arg ip "$ip" '{ok:false,error:"invalid ipv4 octet",ip:$ip}' >&2
        exit 1
    fi
    family="v4"
elif [[ "$ip" == *:* ]]; then
    # IPv6 — getent veya python ile validate
    if command -v python3 &>/dev/null; then
        if ! python3 -c "import ipaddress; ipaddress.ip_network('$ip', strict=False)" &>/dev/null; then
            jq -nc --arg ip "$ip" '{ok:false,error:"invalid ipv6/cidr",ip:$ip}' >&2
            exit 1
        fi
    fi
    family="v6"
else
    jq -nc --arg ip "$ip" '{ok:false,error:"unrecognized ip format",ip:$ip}' >&2
    exit 1
fi

# ── Ensure infra ──────────────────────────────────────────────────────────
nft list table inet onox &>/dev/null || nft add table inet onox

readonly SET_V4="onox-trusted"
readonly SET_V6="onox-trusted-v6"

nft list set inet onox "$SET_V4" &>/dev/null || \
    nft "add set inet onox $SET_V4 { type ipv4_addr; flags interval; auto-merge; }"
nft list set inet onox "$SET_V6" &>/dev/null || \
    nft "add set inet onox $SET_V6 { type ipv6_addr; flags interval; auto-merge; }"

# Trusted_in chain ve accept kuralları (idempotent)
if ! nft list chain inet onox trusted_in &>/dev/null; then
    nft 'add chain inet onox trusted_in { type filter hook input priority -100; }'
    nft "add rule inet onox trusted_in ip saddr @$SET_V4 counter accept comment \"onox-trusted-v4\""
    nft "add rule inet onox trusted_in ip6 saddr @$SET_V6 counter accept comment \"onox-trusted-v6\""
fi

# ── Add element ───────────────────────────────────────────────────────────
target_set=""
if [[ "$family" == "v4" ]]; then
    target_set="$SET_V4"
else
    target_set="$SET_V6"
fi

# nft "add element" — IP zaten varsa hata vermez (file scope)
if ! nft "add element inet onox $target_set { $ip }" 2>/tmp/onox-nft-err-$$; then
    err="$(cat /tmp/onox-nft-err-$$ 2>/dev/null || echo unknown)"
    rm -f /tmp/onox-nft-err-$$
    # "File exists" hatası beklenen — zaten var
    if [[ "$err" == *"File exists"* ]] || [[ "$err" == *"already exists"* ]]; then
        already=true
    else
        jq -nc --arg ip "$ip" --arg err "$err" \
            '{ok:false,error:"nft add element failed",ip:$ip,nft_err:$err}' >&2
        exit 4
    fi
fi
rm -f /tmp/onox-nft-err-$$

logger -t "onox-trusted" "Added $ip to $target_set (family=$family)"

jq -nc --arg ip "$ip" --arg set "$target_set" --arg family "$family" \
    '{ok:true,ip:$ip,set:$set,family:$family}'
