/*
 * DF-3341 harness -- TIM IE parsed without length verification
 * (ieee80211_input.c:586-589 scan->tim = frm) and consumed by
 * ieee80211_scan_sta.c:348-351 reading tim->tim_period (byte 4).
 *
 * struct ieee80211_tim_ie { tim_ie; tim_len; tim_count; tim_period; ... }
 * (ieee80211.h:952-956).  A beacon TIM IE with declared length < 3
 * yields a read of tim_period past the IE end (stale mbuf bytes drive
 * the scan-cache DTIM period).
 */
#include "guard.h"

struct ieee80211_tim_ie {
	uint8_t	tim_ie;
	uint8_t	tim_len;
	uint8_t	tim_count;
	uint8_t	tim_period;
} __packed;

static const struct ieee80211_tim_ie *scan_tim;

/* verbatim: parse_beacon TIM case */
static void
parse_beacon_tim(uint8_t *frm)
{
	scan_tim = (const struct ieee80211_tim_ie *)frm;	/* no len check */
}

/* verbatim: scan_sta consumer */
static int
consume_tim(void)
{
	return scan_tim->tim_period;		/* byte 4 */
}

	static uint8_t *ie;
	static int v;

static uint8_t *ie;
static int v;

int
main(int argc, char **argv)
{
	int oob = (argc > 1 && argv[1][0] == 'o');

	printf("DF-3341 (TIM IE length never checked; tim_period read)\n");
	ie = guard_buf(oob ? 3 : 8);
	ie[0] = 4; ie[1] = oob ? 1 : 5;
	ie[2] = 0;
	printf("  TIM IE declared len=%d; consumer reads tim_period (byte 4)\n", ie[1]);
	fflush(stdout);
#ifdef FIXED
	/* DF-3341 fix: TIM IE must carry at least count+period */
	if (ie[1] < 2) {
		printf("FIXED: TIM IE len %d < 2, ignored\n", ie[1]);
		return 0;
	}
#endif
	parse_beacon_tim(ie);
	v = consume_tim();
	printf("  ran (in bounds), tim_period=%d\n", v);
	return 0;
}
