Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Jan 2004 17:38:44 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 46108 for review
Message-ID:  <200401290138.i0T1ciXo044138@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=46108

Change 46108 by sam@sam_ebb on 2004/01/28 17:38:15

	o add error status reponses for error conditions encountered
	  in shared key authentication
	o hack the ieee80211_send_mgmt so the arg parameter for AUTH
	  frames is interpreted to have the status code in the upper
	  16 bits; this allows error status codes to be returned w/o
	  modifying any existing code

Affected files ...

.. //depot/projects/netperf+sockets/sys/net80211/ieee80211_input.c#9 edit
.. //depot/projects/netperf+sockets/sys/net80211/ieee80211_output.c#9 edit

Differences ...

==== //depot/projects/netperf+sockets/sys/net80211/ieee80211_input.c#9 (text+ko) ====

@@ -752,19 +752,27 @@
 	}
 }
 
-/* TBD send appropriate responses on error? */
 static void
 ieee80211_auth_shared(struct ieee80211com *ic, struct ieee80211_frame *wh,
     u_int8_t *frm, u_int8_t *efrm, struct ieee80211_node *ni, int rssi,
     u_int32_t rstamp, u_int16_t seq, u_int16_t status)
 {
 	u_int8_t *challenge = NULL;
-	int allocbs, i;
+	int allocbs, i, estatus;
 
 	if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) {
 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 			("%s: WEP is off\n", __func__));
-		return;
+		estatus = IEEE80211_STATUS_ALG;
+		goto bad;
+	}
+	if (ic->ic_authmode != IEEE80211_AUTH_AUTO &&
+	    ic->ic_authmode != IEEE80211_AUTH_SHARED) {
+		IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
+			("%s: operating in %u mode, reject\n",
+			 __func__, ic->ic_authmode));
+		estatus = IEEE80211_STATUS_ALG;
+		goto bad;
 	}
 
 	if (frm + 1 < efrm) {
@@ -773,7 +781,8 @@
 				("%s: elt %d %d bytes too long\n", __func__,
 				frm[0], (frm[1] + 2) - (efrm - frm)));
 			ic->ic_stats.is_rx_bad_auth++;
-			return;
+			estatus = IEEE80211_STATUS_CHALLENGE;
+			goto bad;
 		}
 		if (*frm == IEEE80211_ELEMID_CHALLENGE)
 			challenge = frm;
@@ -786,14 +795,16 @@
 			IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 				("%s: no challenge sent\n", __func__));
 			ic->ic_stats.is_rx_bad_auth++;
-			return;
+			estatus = IEEE80211_STATUS_CHALLENGE;
+			goto bad;
 		}
 		if (challenge[1] != IEEE80211_CHALLENGE_LEN) {
 			IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 				("%s: bad challenge len %d\n",
 				__func__, challenge[1]));
 			ic->ic_stats.is_rx_bad_auth++;
-			return;
+			estatus = IEEE80211_STATUS_CHALLENGE;
+			goto bad;
 		}
 	default:
 		break;
@@ -809,7 +820,8 @@
 		if (ic->ic_state != IEEE80211_S_RUN) {
 			IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 				("%s: not running\n", __func__));
-			return;
+			estatus = IEEE80211_STATUS_ALG;	/* XXX */
+			goto bad;
 		}
 		switch (seq) {
 		case IEEE80211_AUTH_SHARED_REQUEST:
@@ -817,6 +829,7 @@
 				ni = ieee80211_alloc_node(ic, wh->i_addr2);
 				if (ni == NULL) {
 					ic->ic_stats.is_rx_nodealloc++;
+					/* NB: no way to return an error */
 					return;
 				}
 				IEEE80211_ADDR_COPY(ni->ni_bssid,
@@ -836,6 +849,7 @@
 					("%s: challenge alloc failed\n",
 					__func__));
 				/* XXX statistic */
+				/* NB: don't return error so they rexmit */
 				return;
 			}
 			for (i = IEEE80211_CHALLENGE_LEN / sizeof(u_int32_t);
@@ -851,6 +865,7 @@
 			if (ni == ic->ic_bss) {
 				IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 					("%s: unknown STA\n", __func__));
+				/* NB: don't send a response */
 				return;
 			}
 			allocbs = 1;
@@ -858,14 +873,16 @@
 				IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 				    ("%s: no challenge recorded\n", __func__));
 				ic->ic_stats.is_rx_bad_auth++;
-				return;
+				estatus = IEEE80211_STATUS_CHALLENGE;
+				goto bad;
 			}
 			if (memcmp(ni->ni_challenge, &challenge[2],
 			           challenge[1]) != 0) {
 				IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH,
 					("%s: challenge mismatch\n", __func__));
 				ic->ic_stats.is_rx_auth_fail++;
-				return;
+				estatus = IEEE80211_STATUS_CHALLENGE;
+				goto bad;
 			}
 			IEEE80211_DPRINTF(ic,
 				IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
@@ -877,7 +894,8 @@
 				("%s: bad shared key auth seq %d from %s\n",
 				__func__, seq, ether_sprintf(wh->i_addr2)));
 			ic->ic_stats.is_rx_bad_auth++;
-			return;
+			estatus = IEEE80211_STATUS_SEQUENCE;
+			goto bad;
 		}
 		IEEE80211_SEND_MGMT(ic, ni,
 			IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
@@ -930,6 +948,17 @@
 		}
 		break;
 	}
+	return;
+bad:
+	/*
+	 * Send an error response; but only when operating as an AP.
+	 */
+	if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+		/* XXX hack to workaround calling convention */
+		IEEE80211_SEND_MGMT(ic, ni,
+			IEEE80211_FC0_SUBTYPE_AUTH,
+			(seq + 1) | (estatus<<16));
+	}
 }
 
 /* Verify the existence and length of __elem or get out. */
@@ -1283,6 +1312,12 @@
 				("%s: unsupported auth algorithm %d from %s\n",
 				__func__, algo, ether_sprintf(wh->i_addr2)));
 			ic->ic_stats.is_rx_auth_unsupported++;
+			if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+				/* XXX not right */
+				IEEE80211_SEND_MGMT(ic, ni,
+					IEEE80211_FC0_SUBTYPE_AUTH,
+					(seq+1) | (IEEE80211_STATUS_ALG<<16));
+			}
 			return;
 		} 
 		break;

==== //depot/projects/netperf+sockets/sys/net80211/ieee80211_output.c#9 (text+ko) ====

@@ -317,7 +317,7 @@
 	u_int8_t *frm;
 	enum ieee80211_phymode mode;
 	u_int16_t capinfo;
-	int has_challenge, is_shared_key, ret, timer;
+	int has_challenge, is_shared_key, ret, timer, status;
 
 	KASSERT(ni != NULL, ("null node"));
 
@@ -428,6 +428,8 @@
 		break;
 
 	case IEEE80211_FC0_SUBTYPE_AUTH:
+		status = arg >> 16;
+		arg &= 0xffff;
 		has_challenge = ((arg == IEEE80211_AUTH_SHARED_CHALLENGE ||
 		    arg == IEEE80211_AUTH_SHARED_RESPONSE) &&
 		    ni->ni_challenge != NULL);
@@ -446,7 +448,7 @@
 
 		m = ieee80211_getmgtframe(&frm,
 			  3 * sizeof(u_int16_t)
-			+ (has_challenge ?
+			+ (has_challenge && status == IEEE80211_STATUS_SUCCESS ?
 				sizeof(u_int16_t)+IEEE80211_CHALLENGE_LEN : 0));
 		if (m == NULL)
 			senderr(ENOMEM, is_tx_nobuf);
@@ -455,9 +457,9 @@
 		    (is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED)
 		                    : htole16(IEEE80211_AUTH_ALG_OPEN);
 		((u_int16_t *)frm)[1] = htole16(arg);	/* sequence number */
-		((u_int16_t *)frm)[2] = 0;		/* status */
+		((u_int16_t *)frm)[2] = htole16(status);/* status */
 
-		if (has_challenge) {
+		if (has_challenge && status == IEEE80211_STATUS_SUCCESS) {
 			((u_int16_t *)frm)[3] =
 			    htole16((IEEE80211_CHALLENGE_LEN << 8) |
 			    IEEE80211_ELEMID_CHALLENGE);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200401290138.i0T1ciXo044138>