# DF-4882 — onoe ath_rate_ctl_start() reachable KASSERT panic via rate-less IBSS beacon

## What
`sys/dev/netif/ath/ath_rate/onoe/onoe.c:285`:

```c
KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates"));
```

DragonFly's default kernel config ships `options INVARIANTS`
(`sys/config/X86_64_GENERIC:56`, verified in the running guest), so KASSERT
is an active panic in production. A single unauthenticated 802.11
beacon/probe-response with a **zero-length Supported Rates IE** (and IBSS
capability bit), received by an ath(4) interface running in adhoc (IBSS)
mode with the onoe ratectl module attached, reaches this KASSERT and panics
the kernel.

## Full static chain (every hop verified in-tree)
1. `adhoc_recv_mgmt` processes BEACON/PROBE_RESP frames — unauthenticated
   (`sys/netproto/802_11/wlan/ieee80211_adhoc.c:678-699`).
2. `ieee80211_parse_beacon` only *flags* a missing RATES element
   (`IEEE80211_BPARSE_RATES_INVALID`, ieee80211_input.c:667-668) — a
   **zero-length** RATES IE passes `IEEE80211_VERIFY_ELEMENT` (checks
   `ie[1] > maxlen` only — ieee80211_input.h:31-41; 0 <= 15) with clean
   status.
3. IBSS capinfo + unknown addr2 → `ieee80211_add_neighbor`
   (ieee80211_adhoc.c:727-735).
4. `ieee80211_init_neighbor` → `ieee80211_setup_rates(ni, sp->rates, ...)`
   with `rates[1] == 0` → `rs_nrates = 0` → `ieee80211_fix_rate` loop body
   never executes → `okrate == 0` → returns error
   (`sys/netproto/802_11/wlan/ieee80211_proto.c:682,746-748`) —
   **and the return value is ignored** (ieee80211_node.c:1559-1561).
5. `ieee80211_add_neighbor` proceeds unconditionally to
   `ic->ic_newassoc(ni, 1)` (ieee80211_node.c:1607-1608).
6. `ath_newassoc` → `ath_rate_newassoc(sc, an, isnew)`
   (sys/dev/netif/ath/ath/if_ath.c:1271, ~ath_newassoc body).
7. onoe.c:189-190 `isnew` → `ath_rate_ctl_start` → **KASSERT panic**
   (onoe.c:285). The very next lines (onoe.c:316-321) explicitly document
   that nodes without a rate set are expected here ("orphaned nodes created
   in adhoc mode may not have any rate set ... This is not fatal") — but on
   INVARIANTS kernels the KASSERT fires first and it *is* fatal.

The amrr sibling has the identical KASSERT (`amrr.c:312`, filed separately
as context only; this pack covers onoe).

## Threat model
Unauthenticated radio-range peer (IBSS participant or spoofer of the cell's
BSSID) → kernel panic = remote DoS. Preconditions: Atheros NIC + onoe
ratectl module attached (sample is the shipped default, X86_64_GENERIC:266)
+ IBSS/adhoc vap + INVARIANTS kernel (the default).

## Why not reproduced on the QEMU guest
The guest has no Atheros NIC (pciconf shows only a virtio vgapci) and no
onoe.ko module (env.txt). The chain is proven statically end-to-end above.

## Fix
Replace the KASSERT with the graceful fallback the surrounding code already
implements (drop the rate-ctl start for empty rate sets), matching the
code's own comment that this case "is not fatal". See fix.diff.
