summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2005-12-04 04:50:27 +0000
committersam <sam@FreeBSD.org>2005-12-04 04:50:27 +0000
commit9c83a5df857df6b616a5b24642d21c8c1effeb47 (patch)
tree838307e708a0af26b07b988f4621aba665160f1b
parent522e9c2b7b1ceeb0bc6a2edb3ee62885d8106ac3 (diff)
downloadFreeBSD-src-9c83a5df857df6b616a5b24642d21c8c1effeb47.zip
FreeBSD-src-9c83a5df857df6b616a5b24642d21c8c1effeb47.tar.gz
Adhoc mode fixups:
o plug memory leak in adhoc mode: on rx the sender may be the current master so simply checking against ic_bss is not enough to identify if the packet comes from an unknown sender; must also check the mac address o split neighbor node creation into two routines and fillin state of nodes faked up on xmit when a beacon or probe response frame is later received; this ensures important state like the rate set and advertised capabilities are correct Obtained from: netbsd MFC after: 1 week
-rw-r--r--sys/net80211/ieee80211_input.c29
-rw-r--r--sys/net80211/ieee80211_node.c52
-rw-r--r--sys/net80211/ieee80211_node.h3
3 files changed, 56 insertions, 28 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 02232b6..1b3c3fb 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -233,7 +233,8 @@ ieee80211_input(struct ieee80211com *ic, struct mbuf *m,
* exist. This should probably done after an ACL check.
*/
if (ni == ic->ic_bss &&
- ic->ic_opmode != IEEE80211_M_HOSTAP) {
+ ic->ic_opmode != IEEE80211_M_HOSTAP &&
+ !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
/*
* Fake up a node for this newly
* discovered member of the IBSS.
@@ -1957,6 +1958,12 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
* Create a new entry in the neighbor table.
*/
ni = ieee80211_add_neighbor(ic, wh, &scan);
+ } else if (ni->ni_capinfo == 0) {
+ /*
+ * Update faked node created on transmit.
+ * Note this also updates the tsf.
+ */
+ ieee80211_init_neighbor(ni, wh, &scan);
} else {
/*
* Record tsf for potential resync.
@@ -2017,8 +2024,12 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
return;
}
+ allocbs = 0;
if (ni == ic->ic_bss) {
- if (ic->ic_opmode == IEEE80211_M_IBSS) {
+ if (ic->ic_opmode != IEEE80211_M_IBSS) {
+ ni = ieee80211_tmp_node(ic, wh->i_addr2);
+ allocbs = 1;
+ } else if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
/*
* XXX Cannot tell if the sender is operating
* in ibss mode. But we need a new node to
@@ -2027,13 +2038,10 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
*/
ni = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
wh->i_addr2);
- } else
- ni = ieee80211_tmp_node(ic, wh->i_addr2);
+ }
if (ni == NULL)
return;
- allocbs = 1;
- } else
- allocbs = 0;
+ }
IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
"[%s] recv probe req\n", ether_sprintf(wh->i_addr2));
ni->ni_rssi = rssi;
@@ -2050,8 +2058,11 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
IEEE80211_SEND_MGMT(ic, ni,
IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);
}
- if (allocbs && ic->ic_opmode != IEEE80211_M_IBSS) {
- /* reclaim immediately */
+ if (allocbs) {
+ /*
+ * Temporary node created just to send a
+ * response, reclaim immediately.
+ */
ieee80211_free_node(ni);
}
break;
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index d4f59ef..567c499 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -1077,6 +1077,8 @@ ieee80211_fakeup_adhoc_node(struct ieee80211_node_table *nt,
struct ieee80211com *ic = nt->nt_ic;
struct ieee80211_node *ni;
+ IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
+ "%s: mac<%s>\n", __func__, ether_sprintf(macaddr));
ni = ieee80211_dup_bss(nt, macaddr);
if (ni != NULL) {
/* XXX no rate negotiation; just dup */
@@ -1218,6 +1220,34 @@ ieee80211_add_scan(struct ieee80211com *ic,
#undef ISPROBE
}
+void
+ieee80211_init_neighbor(struct ieee80211_node *ni,
+ const struct ieee80211_frame *wh,
+ const struct ieee80211_scanparams *sp)
+{
+
+ IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
+ "%s: %p<%s>\n", __func__, ni, ether_sprintf(ni->ni_macaddr));
+ ni->ni_esslen = sp->ssid[1];
+ memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
+ IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
+ memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
+ ni->ni_intval = sp->bintval;
+ ni->ni_capinfo = sp->capinfo;
+ ni->ni_chan = ni->ni_ic->ic_curchan;
+ ni->ni_fhdwell = sp->fhdwell;
+ ni->ni_fhindex = sp->fhindex;
+ ni->ni_erp = sp->erp;
+ ni->ni_timoff = sp->timoff;
+ if (sp->wme != NULL)
+ ieee80211_saveie(&ni->ni_wme_ie, sp->wme);
+ if (sp->wpa != NULL)
+ ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa);
+
+ /* NB: must be after ni_chan is setup */
+ ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT);
+}
+
/*
* Do node discovery in adhoc mode on receipt of a beacon
* or probe response frame. Note that for the driver's
@@ -1231,27 +1261,11 @@ ieee80211_add_neighbor(struct ieee80211com *ic,
{
struct ieee80211_node *ni;
+ IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
+ "%s: mac<%s>\n", __func__, ether_sprintf(wh->i_addr2));
ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);/* XXX alloc_node? */
if (ni != NULL) {
- ni->ni_esslen = sp->ssid[1];
- memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
- IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
- memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
- ni->ni_intval = sp->bintval;
- ni->ni_capinfo = sp->capinfo;
- ni->ni_chan = ic->ic_bss->ni_chan;
- ni->ni_fhdwell = sp->fhdwell;
- ni->ni_fhindex = sp->fhindex;
- ni->ni_erp = sp->erp;
- ni->ni_timoff = sp->timoff;
- if (sp->wme != NULL)
- ieee80211_saveie(&ni->ni_wme_ie, sp->wme);
- if (sp->wpa != NULL)
- ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa);
-
- /* NB: must be after ni_chan is setup */
- ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT);
-
+ ieee80211_init_neighbor(ni, wh, sp);
if (ic->ic_newassoc != NULL)
ic->ic_newassoc(ni, 1);
/* XXX not right for 802.1x/WPA */
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index e2bfc2c..65acdc0 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -324,6 +324,9 @@ void ieee80211_add_scan(struct ieee80211com *,
const struct ieee80211_scanparams *,
const struct ieee80211_frame *,
int subtype, int rssi, int rstamp);
+void ieee80211_init_neighbor(struct ieee80211_node *,
+ const struct ieee80211_frame *,
+ const struct ieee80211_scanparams *);
struct ieee80211_node *ieee80211_add_neighbor(struct ieee80211com *,
const struct ieee80211_frame *,
const struct ieee80211_scanparams *);
OpenPOWER on IntegriCloud