diff options
author | sam <sam@FreeBSD.org> | 2006-03-06 17:26:16 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2006-03-06 17:26:16 +0000 |
commit | 4da3fa06be32d533324cca008f33c7d5d294fb74 (patch) | |
tree | ca7e878eee81b18ecad79fc55f17a9f34c4c3ec0 /sys/net80211/ieee80211_input.c | |
parent | d3539a10d4a53f5fd3a54756999431b21064ff5e (diff) | |
download | FreeBSD-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/ieee80211_input.c')
-rw-r--r-- | sys/net80211/ieee80211_input.c | 51 |
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; } |