/*
 * DF-3343 harness -- ieee80211_media_setup indexes the const
 * ieee80211_htrates[77] table with ic_txstream*8-1 and NO clamp.
 *
 * VERBATIM ieee80211.c:1620-1629:
 *	i = ic->ic_txstream * 8 - 1;
 *	if ((ic->ic_htcaps & CHWIDTH40) && (SHORTGI40))
 *		rate = ieee80211_htrates[i].ht40_rate_400ns;
 *	else if ...
 *		rate = ieee80211_htrates[i].ht20_rate_800ns;
 *
 * ieee80211_htrates has IEEE80211_HTRATE_MAXSIZE = 77 entries
 * (_ieee80211.h:388).  ic_txstream is a driver-set u_int (1..4 on
 * correct drivers); any driver/HAL value > 10 indexes past the table.
 * The real table is const data in .rodata; we demonstrate with a
 * private copy at a guard boundary (same index arithmetic).
 */
#include "guard.h"

#define	IEEE80211_HTRATE_MAXSIZE	77

struct ieee80211_mcs_rates {
	uint16_t	ht20_rate_800ns;
	uint16_t	ht20_rate_400ns;
	uint16_t	ht40_rate_800ns;
	uint16_t	ht40_rate_400ns;
};

/* copy of the const table shape; contents identical for MCS0-3 */
static struct ieee80211_mcs_rates *
table_at_guard(void)
{
	struct ieee80211_mcs_rates *t =
	    (struct ieee80211_mcs_rates *)guard_buf(
	        IEEE80211_HTRATE_MAXSIZE * sizeof(struct ieee80211_mcs_rates));
	memset(t, 0, IEEE80211_HTRATE_MAXSIZE * sizeof(*t));
	t[0].ht20_rate_800ns = 13;	/* MCS0 values from ieee80211_ht.c */
	t[1].ht20_rate_800ns = 26;
	return t;
}

	static struct ieee80211_mcs_rates *htrates;
	static int rate;

static struct ieee80211_mcs_rates *htrates;
static int rate;

int
main(int argc, char **argv)
{
	int oob = (argc > 1 && argv[1][0] == 'o');
	unsigned txstream = oob ? 20 : 4;
	int i = txstream * 8 - 1;

	printf("DF-3343 (ic_txstream*8-1 unclamped into htrates[77],"
	    " ieee80211.c:1620-1629)\n");
	printf("  txstream=%u -> index %d (%d entries past the 77-entry"
	    " table)\n", txstream, i, i >= 77 ? i - 76 : 0);
	htrates = table_at_guard();
	printf("  rate = ieee80211_htrates[i].ht20_rate_800ns\n");
	fflush(stdout);
#ifdef FIXED
	/* DF-3343 fix: clamp the MCS index into the table */
	if (i >= IEEE80211_HTRATE_MAXSIZE) {
		printf("FIXED: index %d clamped (txstream misconfigured)\n", i);
		i = IEEE80211_HTRATE_MAXSIZE - 1;
	}
#endif
	rate = htrates[i].ht20_rate_800ns;
	printf("  ran (in bounds), rate=%d\n", rate);
	return 0;
}
