summaryrefslogtreecommitdiffstats
path: root/sys/dev/wi/if_wi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/wi/if_wi.c')
-rw-r--r--sys/dev/wi/if_wi.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 172beb3..a4a74e4 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
+#include <net/if_llc.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -978,6 +979,7 @@ wi_start_locked(struct ifnet *ifp)
struct mbuf *m0;
struct ieee80211_key *k;
struct wi_frame frmhdr;
+ const struct llc *llc;
int cur;
WI_LOCK_ASSERT(sc);
@@ -996,19 +998,33 @@ wi_start_locked(struct ifnet *ifp)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
- /* NB: copy before 802.11 header is prepended */
- m_copydata(m0, 0, ETHER_HDR_LEN,
- (caddr_t)&frmhdr.wi_ehdr);
-
ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
- m0 = ieee80211_encap(ni, m0);
- if (m0 == NULL) {
- ifp->if_oerrors++;
- ieee80211_free_node(ni);
- continue;
- }
+ /* reconstruct 802.3 header */
wh = mtod(m0, struct ieee80211_frame *);
+ switch (wh->i_fc[1]) {
+ case IEEE80211_FC1_DIR_TODS:
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_shost,
+ wh->i_addr2);
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_dhost,
+ wh->i_addr3);
+ break;
+ case IEEE80211_FC1_DIR_NODS:
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_shost,
+ wh->i_addr2);
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_dhost,
+ wh->i_addr1);
+ break;
+ case IEEE80211_FC1_DIR_FROMDS:
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_shost,
+ wh->i_addr3);
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_dhost,
+ wh->i_addr1);
+ break;
+ }
+ llc = (const struct llc *)(
+ mtod(m0, const uint8_t *) + ieee80211_hdrsize(wh));
+ frmhdr.wi_ehdr.ether_type = llc->llc_snap.ether_type;
frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX);
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
k = ieee80211_crypto_encap(ni, m0);
OpenPOWER on IntegriCloud