# DF-0571 — ipfw3_nat panic on non-TCP/UDP/ICMP packet

## Bug
`ip_fw3_nat()` at sys/net/ipfw3_nat/ip_fw3_nat.c contains two switch
statements over `ip->ip_p` with default cases that call
`panic("ipfw3: unsupported proto %u", ip->ip_p)`:

- inbound switch  — line 219
- outbound switch — line 254

Any IP packet whose protocol is not TCP (6), UDP (17), or ICMP (1) and
that matches an ipfw3 NAT rule will crash the kernel instantly. Common
protocols affected: SCTP (132), GRE (47), ESP (50), AH (51), IGMP (2),
UDPLite (136).

The outbound switch (line 254) has no NAT/alias gate before it, so any
internal host emitting such a protocol through a NAT rule panics the
router. Network input paths must never panic on adversarial input.

## Setup
- Requires `ipfw3`, `ipfw3_basic`, `ipfw3_nat` KLDs loaded.
- Set `net.filters_default_to_accept=1` in `/boot/loader.conf.local` so
  ssh survives the load (otherwise ipfw3 defaults to deny-all).
- Configure: `ipfw3 nat 1 config ip <ifaddr>` and add a NAT rule.

## Reproduce
```
./build.sh
ssh dfbsd /root/setup.sh      # configures NAT rule
./run.sh                       # as root, sends SCTP (proto 132) packet
# kernel panic: panic: ipfw3: unsupported proto 132 at ip_fw3_nat+0x7f
```

The raw_trigger PoC uses an `IPPROTO_RAW` socket to inject an IP packet
with `ip_p = 132` (SCTP). The PFIL hook on IPv4 output routes the packet
through ip_fw3_check_out → ip_fw3_chk → check_nat → ip_fw3_nat, which
hits `default: panic()`.

Triggering from an unprivileged user is not directly possible on this
guest (raw IP sockets require SYSCAP_NONET_RAW). The realistic threat
model is a router running NAT: any internal host emitting SCTP/GRE/ESP
through a NAT'd interface crashes the router.

## Fix
Replace `panic(...)` at lines 219 and 254 with `goto oops;` (IP_FW_DENY).
The inner switch (state-creation, around line 267-330) already uses
`goto oops` for unknown protocols — this fix makes the outer switches
consistent. See fix.diff.
