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>