# DF-3276 — bridge span-port NULL dereference → deterministic kernel panic

## What

`bridge_span()` hands mirrored packets to `bridge_enqueue()`, whose
netmsg handler dereferences `dst_ifp->if_bridge` — but **span ports
never get `if_bridge` set** (only member add does,
sys/net/bridge/if_bridge.c:1300; `bridge_ioctl_addspan` never assigns
it, and `bridge_delete_span` KASSERTs it is NULL,
sys/net/bridge/if_bridge.c:1152).  The first packet mirrored to a span
port (or the first locally-originated packet once a span port exists)
panics the kernel:

```
bridge_input()/bridge_output()
  -> bridge_span()                    if_bridge.c:3258
     -> bridge_enqueue(span_ifp)      if_bridge.c:3279
        -> bridge_enqueue_handler()   if_bridge.c:4418
           bridge_handoff(dst_ifp->if_bridge /* == NULL */, ...)
        -> bridge_handoff()           if_bridge.c:4433
           bifp = sc->sc_ifp;         if_bridge.c:4440   <-- NULL+0x3b8 fault
```

## Reproduce (guest, as root)

```
cd /root/poc/df-3276
cc -O -o span_panic span_panic.c
sh run.sh          # creates bridge0 + tap0/tap1/tap2, adds tap2 as span port, injects
```

## Expected

Immediate kernel panic:

```
Fatal trap 12: page fault while in kernel mode
fault virtual address = 0x3b8
Stopped at bridge_handoff+0x11: movq 0x3b8(%rdi),%rax      # rdi == NULL (sc)
```

(0x3b8 = offsetof(struct bridge_softc, sc_ifp).)

In the captured baseline run the panic was triggered by the bridge's
own IPv6 DAD output (`bridge_output()` also calls `bridge_span()` at
if_bridge.c:2241/2358) right after the span port was configured — no
attacker-injected frame is even needed; any frame through the bridge
works.  The tree is byte-identical to DragonFlyBSD master as of the
audit, so this is a live upstream bug.

## Fix

`fix.diff` — mirror directly via `bridge_handoff(sc, dst_if, mc, 0)`
(also correct: span must not rewrite the source MAC), plus a defensive
NULL guard in `bridge_enqueue_handler()` for the member-deletion race.
