From 9c83a5df857df6b616a5b24642d21c8c1effeb47 Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 4 Dec 2005 04:50:27 +0000 Subject: 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 --- sys/net80211/ieee80211_input.c | 29 +++++++++++++++-------- sys/net80211/ieee80211_node.c | 52 +++++++++++++++++++++++++++--------------- sys/net80211/ieee80211_node.h | 3 +++ 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 *); -- cgit v1.1