/*
 * DF-3374 harness -- ieee80211_parse_csaparams() consumes the CSA IE
 * with no validation of its declared length.
 *
 * VERBATIM ieee80211_sta.c:1146-1200 (extract of the field reads):
 *	const struct ieee80211_csa_ie *csa = (const void *)frm;
 *	if (csa->csa_mode > 1) ...        (byte 2)
 *	    csa->csa_newchan              (byte 3)
 *	    csa->csa_count                (byte 4)
 * struct ieee80211_csa_ie { ie; len; mode; newchan; count } (802.11.h:1063)
 * caller sta.c:1472 passes scan.csa straight from the beacon walk
 * (ieee80211_input.c:565 case IEEE80211_ELEMID_CSA: scan->csa = frm).
 * A CSA IE with declared len < 3 drives reads up to 3 bytes past the IE.
 */
#include "guard.h"

struct ieee80211_csa_ie {
	uint8_t	csa_ie;
	uint8_t	csa_len;
	uint8_t	csa_mode;
	uint8_t	csa_newchan;
	uint8_t	csa_count;
} __packed;

/* verbatim shape of the field consumption (channel lookups stubbed) */
static int
ieee80211_parse_csaparams(uint8_t *frm)
{
	const struct ieee80211_csa_ie *csa =
	    (const struct ieee80211_csa_ie *) frm;

	if (csa->csa_mode > 1)
		return -1;			/* invalid mode */
	/* channel switch decision driven by: */
	if (csa->csa_newchan == 0)
		return -1;
	return csa->csa_count;		/* switch count */
}

	static uint8_t *ie;
	static int r, which;

static uint8_t *ie;
static int r;

int
main(int argc, char **argv)
{
	int which = (argc > 1) ? atoi(argv[1]) : 0;

	printf("DF-3374 (parse_csaparams: no frm[1] check)\n");
	if (which == 2) {
		ie = guard_buf(4);
		ie[0] = 37; ie[1] = 2; ie[2] = 0; ie[3] = 36;
		printf("  CSA len=2: csa_count (byte 4) past the IE\n");
	} else if (which == 1) {
		ie = guard_buf(3);
		ie[0] = 37; ie[1] = 1; ie[2] = 0;
		printf("  CSA len=1: csa_newchan (byte 3) past the IE\n");
	} else {
		ie = guard_buf(8);
		ie[0] = 37; ie[1] = 3; ie[2] = 0; ie[3] = 36; ie[4] = 5;
		printf("  control: well-formed CSA IE\n");
	}
	fflush(stdout);
#ifdef FIXED
	/* DF-3374 fix: CSA IE must carry mode+newchan+count */
	if (ie[1] < 3) {
		printf("FIXED: CSA IE len %d < 3, discarded\n", ie[1]);
		return 0;
	}
#endif
	r = ieee80211_parse_csaparams(ie);
	printf("  ran (in bounds), r=%d\n", r);
	return 0;
}
