Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Feb 2004 14:51:37 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 47060 for review
Message-ID:  <200402162251.i1GMpbk0070590@repoman.freebsd.org>

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

Change 47060 by sam@sam_ebb on 2004/02/16 14:51:00

	o add ieee80211_node_authorize and ieee80211_node_unauthorize
	  to mark ports authorized/unauthorized for data traffic;
	  for use by the 802.1x authenticator
	o add ieee80211_node_makekey to create and install a unicast key
	  for a station; for use by the authenticator
	o use new privacy flag bit instead of "wep is on" flag bit
	o use get_random_bytes portability wrapper instead of explicit
	  arc4random call
	o record node allocation failures where they occur rather in all
	  the call sites
	o make ieee80211_dup_bss properly inherit state from ic_bss
	o use ieee80211_node_leave instead of ieee80211_free_node when
	  timing out a node for inactivty so 11g and .1x state is maintained
	o add ieee80211_dump_node and ieee80211_dump_nodes for dumping the
	  state of the node table
	o move ieee80211_node_leave from elsewhere and expand it to notify
	  the authenticator and to reclaim the refcnt on the node (and
	  possibly the resources too)

Affected files ...

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

Differences ...

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

@@ -126,6 +126,52 @@
 	IEEE80211_NODE_LOCK_DESTROY(ic);
 }
 
+/* 
+ * Port authorize/unauthorize interfaces for use by an authenticator.
+ */
+
+void
+ieee80211_node_authorize(struct ieee80211com *ic, struct ieee80211_node *ni)
+{
+	ni->ni_flags |= IEEE80211_NODE_AUTH;
+}
+
+void
+ieee80211_node_unauthorize(struct ieee80211com *ic, struct ieee80211_node *ni)
+{
+	ni->ni_flags &= ~IEEE80211_NODE_AUTH;
+}
+
+/*
+ * Construct and install a unicast key for the node.
+ * This is typically called by the 802.1x authenticator
+ * as part of arranging key state after a station has
+ * been authorized.
+ */
+int
+ieee80211_node_makekey(struct ieee80211com *ic, struct ieee80211_node *ni)
+{
+	/* XXX use maximally-sized keys; may want to match mcast key length */
+	ni->ni_ucastkey.wk_len = sizeof(ni->ni_ucastkey.wk_key) * NBBY;
+	/* XXX just use random data for now; probably want something better */
+	get_random_bytes(ni->ni_ucastkey.wk_key,
+		sizeof(ni->ni_ucastkey.wk_key));
+	/*
+	 * Hand the new key to the driver so it can be installed
+	 * and so it can allocate a hardware key index.
+	 */
+	ni->ni_ucastkeyix = (*ic->ic_key_add)(ic, &ni->ni_ucastkey);
+	if (ni->ni_ucastkeyix == IEEE80211_KEYIX_NONE) {
+		 /*
+		 * Driver has no room or support for this algorithm;
+		 * fallback to doing crypto in the host.
+		 */
+		/* XXX */
+		return 0;
+	}
+	return 1;
+}
+
 /*
  * AP scanning support.
  */
@@ -233,7 +279,7 @@
 	memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
 	ni->ni_intval = ic->ic_lintval;
 	ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
-	if (ic->ic_flags & IEEE80211_F_WEPON)
+	if (ic->ic_flags & IEEE80211_F_PRIVACY)
 		ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
 	if (ic->ic_phytype == IEEE80211_T_FH) {
 		ni->ni_fhdwell = 200;	/* XXX */
@@ -261,10 +307,11 @@
 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
 			fail |= 0x02;
 	}
-	if (ic->ic_flags & IEEE80211_F_WEPON) {
+	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
 			fail |= 0x04;
 	} else {
+		/* XXX does this mean privacy is supported or required? */
 		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
 			fail |= 0x04;
 	}
@@ -337,7 +384,8 @@
 			if (isset(ic->ic_chan_active, i) && isclr(occupied, i))
 				break;
 		if (i == IEEE80211_CHAN_MAX) {
-			fail = arc4random() & 3;	/* random 0-3 */
+			get_random_bytes(&fail, sizeof(fail));
+			fail &= 3;		/* random 0-3 */
 			for (i = 0; i < IEEE80211_CHAN_MAX; i++)
 				if (isset(ic->ic_chan_active, i) && fail-- == 0)
 					break;
@@ -454,6 +502,8 @@
 {
 	int hash;
 
+	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
+		("%s %s\n", __func__, ether_sprintf(macaddr)));
 	IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
 	hash = IEEE80211_NODE_HASH(macaddr);
 	/* XXX */
@@ -482,6 +532,8 @@
 	struct ieee80211_node *ni = (*ic->ic_node_alloc)(ic);
 	if (ni != NULL)
 		ieee80211_setup_node(ic, ni, macaddr);
+	else
+		ic->ic_stats.is_rx_nodealloc++;
 	return ni;
 }
 
@@ -490,9 +542,17 @@
 {
 	struct ieee80211_node *ni = (*ic->ic_node_alloc)(ic);
 	if (ni != NULL) {
-		memcpy(ni, ic->ic_bss, sizeof(struct ieee80211_node));
 		ieee80211_setup_node(ic, ni, macaddr);
-	}
+		/*
+		 * Inherit from ic_bss.
+		 */
+		ni->ni_authmode = ic->ic_bss->ni_authmode;
+		ni->ni_txpower = ic->ic_bss->ni_txpower;
+		ni->ni_vlan = ic->ic_bss->ni_vlan;	/* XXX?? */
+		IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
+		ni->ni_chan = ic->ic_bss->ni_chan;
+	} else
+		ic->ic_stats.is_rx_nodealloc++;
 	return ni;
 }
 
@@ -527,7 +587,8 @@
 	hash = IEEE80211_NODE_HASH(macaddr);
 	IEEE80211_NODE_LOCK(ic);
 	LIST_FOREACH(ni, &ic->ic_hash[hash], ni_hash) {
-		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr) && ni->ni_chan == chan) {
+		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr) &&
+		    ni->ni_chan == chan) {
 			ieee80211_node_incref(ni);/* mark referenced */
 			break;
 		}
@@ -544,8 +605,12 @@
 
 	KASSERT(ni != ic->ic_bss, ("freeing bss node"));
 
+	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
+		("%s %s\n", __func__, ether_sprintf(ni->ni_macaddr)));
 	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
 	TAILQ_REMOVE(&ic->ic_node, ni, ni_list);
+	if (TAILQ_EMPTY(&ic->ic_node))
+		ic->ic_inact_timer = 0;
 	LIST_REMOVE(ni, ni_hash);
 	if (_IF_QLEN(&ni->ni_savedq) != 0) {
 		/*
@@ -556,8 +621,6 @@
 			ic->ic_set_tim(ic, ni->ni_associd, 0);
 	}
 	mtx_destroy(&ni->ni_savedq.ifq_mtx);	/* XXX */
-	if (TAILQ_EMPTY(&ic->ic_node))
-		ic->ic_inact_timer = 0;
 	for (i = 0; i < N(ni->ni_rxfrag); i++)
 		if (ni->ni_rxfrag[i] != NULL)
 			m_freem(ni->ni_rxfrag[i]);
@@ -570,6 +633,9 @@
 {
 	KASSERT(ni != ic->ic_bss, ("freeing ic_bss"));
 
+	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
+		("%s %s refcnt %d\n", __func__,
+		 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)));
 	if (ieee80211_node_dectestref(ni)) {
 		IEEE80211_NODE_LOCK(ic);
 		_ieee80211_free_node(ic, ni);
@@ -582,6 +648,7 @@
 {
 	struct ieee80211_node *ni;
 
+	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE, ("free all nodes\n"));
 	IEEE80211_NODE_LOCK(ic);
 	while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL)
 		_ieee80211_free_node(ic, ni);  
@@ -623,7 +690,6 @@
 			    ("station %s timed out due to inactivity (%u secs)\n",
 			    ether_sprintf(ni->ni_macaddr),
 			    ni->ni_inact));
-			ieee80211_node_leave(ic, ni);
 			/*
 			 * Send a deauthenticate frame.
 			 *
@@ -636,7 +702,7 @@
 			IEEE80211_SEND_MGMT(ic, ni,
 			    IEEE80211_FC0_SUBTYPE_DEAUTH,
 			    IEEE80211_REASON_AUTH_EXPIRE);
-			ieee80211_free_node(ic, ni);
+			ieee80211_node_leave(ic, ni);
 			ic->ic_stats.is_node_timeout++;
 			goto restart;
 		}
@@ -656,3 +722,107 @@
 		(*f)(arg, ni);
 	IEEE80211_NODE_UNLOCK(ic);
 }
+
+void
+ieee80211_dump_node(struct ieee80211_node *ni)
+{
+	printf("0x%p: mac %s refcnt %d\n", ni,
+		ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni));
+	printf("\tscangen %u fragno %u authmode %u flags 0x%x\n",
+		ni->ni_scangen, ni->ni_fragno, ni->ni_authmode, ni->ni_flags);
+	printf("\tassocid 0x%x txpower %u vlan %u\n",
+		ni->ni_associd, ni->ni_txpower, ni->ni_vlan);
+	printf("\ttxseq %u rxseq %u rxfragstamp %u\n",
+		ni->ni_txseq, ni->ni_rxseq, ni->ni_rxfragstamp);
+	printf("\trstamp %u rssi %u intval %u capinfo 0x%x\n",
+		ni->ni_rstamp, ni->ni_rssi, ni->ni_intval, ni->ni_capinfo);
+	printf("\tbssid %s essid \"%.*s\" channel %u:0x%x\n",
+		ether_sprintf(ni->ni_bssid),
+		ni->ni_esslen, ni->ni_essid,
+		ni->ni_chan->ic_freq, ni->ni_chan->ic_flags);
+	printf("\tfails %u inact %u txrate %u\n",
+		ni->ni_fails, ni->ni_inact, ni->ni_txrate);
+}
+
+void
+ieee80211_dump_nodes(struct ieee80211com *ic)
+{
+	struct ieee80211_node *ni;
+
+	IEEE80211_NODE_LOCK(ic);
+	TAILQ_FOREACH(ni, &ic->ic_node, ni_list)
+		ieee80211_dump_node(ni);
+	IEEE80211_NODE_UNLOCK(ic);
+}
+
+/*
+ * Handle bookkeeping for station deauthentication/disassociation
+ * when operating as an ap.
+ */
+void
+ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
+{
+	KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP,
+		("not in ap mode, mode %u", ic->ic_opmode));
+	/*
+	 * If node wasn't previously associated all
+	 * we need to do is reclaim the reference.
+	 */
+	if (ni->ni_associd == 0)
+		goto done;
+	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
+	ni->ni_associd = 0;
+
+	/*
+	 * If a long slot station do the slot time bookkeeping.
+	 */
+	if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {
+		KASSERT(ic->ic_longslotsta > 0,
+		    ("bogus long slot station count %d", ic->ic_longslotsta));
+		ic->ic_longslotsta--;
+		IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+			("long slot time station %s leaves, count now %d\n",
+			ether_sprintf(ni->ni_macaddr), ic->ic_longslotsta));
+		if (ic->ic_longslotsta == 0 &&
+		    ic->ic_curmode == IEEE80211_MODE_11G) {
+			/*
+			 * Re-enable use of short slot time if supported
+			 * and not operating in IBSS mode (per spec).
+			 */
+			if ((ic->ic_caps & IEEE80211_C_SHSLOT) &&
+			    ic->ic_opmode != IEEE80211_M_IBSS) {
+				IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+					("re-enable use of short slot time\n"));
+				ic->ic_flags |= IEEE80211_F_SHSLOT;
+			}
+		}
+	}
+	/*
+	 * If a non-ERP station do the protection-related bookkeeping.
+	 */
+	if ((ni->ni_flags & IEEE80211_NODE_ERP) == 0) {
+		KASSERT(ic->ic_nonerpsta > 0,
+		    ("bogus non-ERP station count %d", ic->ic_nonerpsta));
+		ic->ic_nonerpsta--;
+		IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+			("non-ERP station %s leaves, count now %d\n",
+			ether_sprintf(ni->ni_macaddr), ic->ic_nonerpsta));
+		if (ic->ic_nonerpsta == 0) {
+			IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+				("disable use of protection\n"));
+			ic->ic_flags &= ~IEEE80211_F_USEPROT;
+			/* XXX verify mode? */
+			if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) {
+				IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+					("re-enable use of short preamble\n"));
+				ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
+				ic->ic_flags &= ~IEEE80211_F_USEBARKER;
+			}
+		}
+	}
+done:
+	/* tell the authenticator the station is leaving */
+	if (ni->ni_authmode == IEEE80211_AUTH_8021X)
+		(*ic->ic_node_leave)(ic, ni);
+	ieee80211_free_node(ic, ni);
+}



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