summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2006-03-06 17:26:16 +0000
committersam <sam@FreeBSD.org>2006-03-06 17:26:16 +0000
commit4da3fa06be32d533324cca008f33c7d5d294fb74 (patch)
treeca7e878eee81b18ecad79fc55f17a9f34c4c3ec0 /sys/net80211
parentd3539a10d4a53f5fd3a54756999431b21064ff5e (diff)
downloadFreeBSD-src-4da3fa06be32d533324cca008f33c7d5d294fb74.zip
FreeBSD-src-4da3fa06be32d533324cca008f33c7d5d294fb74.tar.gz
deliver an l2uf frame on sta join to prime the bridge
Obtained from: madwifi MFC after: 1 week
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_input.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 965e372..6843f8e 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1711,6 +1711,56 @@ ieee80211_saveie(u_int8_t **iep, const u_int8_t *ie)
/* XXX note failure */
}
+/* XXX find a better place for definition */
+struct l2_update_frame {
+ struct ether_header eh;
+ u_int8_t dsap;
+ u_int8_t ssap;
+ u_int8_t control;
+ u_int8_t xid[3];
+} __packed;
+
+/*
+ * Deliver a TGf L2UF frame on behalf of a station.
+ * This primes any bridge when the station is roaming
+ * between ap's on the same wired network.
+ */
+static void
+ieee80211_deliver_l2uf(struct ieee80211_node *ni)
+{
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct mbuf *m;
+ struct l2_update_frame *l2uf;
+ struct ether_header *eh;
+
+ m = m_gethdr(M_NOWAIT, MT_DATA);
+ if (m == NULL) {
+ IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
+ "%s", "no mbuf for l2uf frame");
+ ic->ic_stats.is_rx_nobuf++; /* XXX not right */
+ return;
+ }
+ l2uf = mtod(m, struct l2_update_frame *);
+ eh = &l2uf->eh;
+ /* dst: Broadcast address */
+ IEEE80211_ADDR_COPY(eh->ether_dhost, ifp->if_broadcastaddr);
+ /* src: associated STA */
+ IEEE80211_ADDR_COPY(eh->ether_shost, ni->ni_macaddr);
+ eh->ether_type = htons(sizeof(*l2uf) - sizeof(*eh));
+
+ l2uf->dsap = 0;
+ l2uf->ssap = 0;
+ l2uf->control = 0xf5;
+ l2uf->xid[0] = 0x81;
+ l2uf->xid[1] = 0x80;
+ l2uf->xid[2] = 0x00;
+
+ m->m_pkthdr.len = m->m_len = sizeof(*l2uf);
+ m->m_pkthdr.rcvif = ifp;
+ ieee80211_deliver_data(ic, ni, m);
+}
+
void
ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
struct ieee80211_node *ni,
@@ -2353,6 +2403,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
ni->ni_wme_ie = NULL;
ni->ni_flags &= ~IEEE80211_NODE_QOS;
}
+ ieee80211_deliver_l2uf(ni);
ieee80211_node_join(ic, ni, resp);
break;
}
OpenPOWER on IntegriCloud