/* * Validate and strip privacy headers (and trailer) for a * received frame that has the WEP/Privacy bit set. */ struct ieee80211_key * ieee80211_crypto_decap(struct ieee80211com *ic, struct ieee80211_node *ni, struct sk_buff *skb) { #define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN) #define IEEE80211_WEP_MINLEN \ (sizeof(struct ieee80211_frame) + ETHER_HDR_LEN + \ IEEE80211_WEP_HDRLEN + IEEE80211_WEP_CRCLEN) struct ieee80211_key *k; struct ieee80211_frame *wh; u_int8_t *ivp; u_int8_t keyid; /* NB: this minimum size data frame could be bigger */ if (skb->len < IEEE80211_WEP_MINLEN) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, ("%s: WEP data frame too short, len %u\n", __func__, skb->len)); ic->ic_stats.is_rx_tooshort++; /* XXX need unique stat? */ return NULL; } /* * Locate the key. If unicast and there is no unicast * key then we fall back to the key id in the header. * This assumes unicast keys are only configured when * the key id in the header is meaningless (typically 0). */ wh = (struct ieee80211_frame *) skb->data; ivp = skb->data + ieee80211_hdrsize(wh); keyid = ivp[IEEE80211_WEP_IVLEN]; if (IEEE80211_IS_MULTICAST(wh->i_addr1) || ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) k = &ic->ic_nw_keys[keyid >> 6]; else
/* * Validate and strip privacy headers (and trailer) for a * received frame that has the WEP/Privacy bit set. */ struct ieee80211_key * ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen) { #define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN) #define IEEE80211_WEP_MINLEN \ (sizeof(struct ieee80211_frame) + \ IEEE80211_WEP_HDRLEN + IEEE80211_WEP_CRCLEN) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k; struct ieee80211_frame *wh; const struct ieee80211_cipher *cip; uint8_t keyid; /* NB: this minimum size data frame could be bigger */ if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, "%s: WEP data frame too short, len %u\n", __func__, m->m_pkthdr.len); vap->iv_stats.is_rx_tooshort++; /* XXX need unique stat? */ return NULL; } /* * Locate the key. If unicast and there is no unicast * key then we fall back to the key id in the header. * This assumes unicast keys are only configured when * the key id in the header is meaningless (typically 0). */ wh = mtod(m, struct ieee80211_frame *); m_copydata(m, hdrlen + IEEE80211_WEP_IVLEN, sizeof(keyid), &keyid); if (IEEE80211_IS_MULTICAST(wh->i_addr1) || IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) k = &vap->iv_nw_keys[keyid >> 6]; else
/*for sending an event to notify hostapd about michael failure. */ VOID ieee80211_notify_michael_failure( IN struct rtmp_adapter * pAd, IN PHEADER_802_11 pHeader, IN UINT keyix, IN INT report) { static const char *tag = "MLME-MICHAELMICFAILURE.indication"; /* struct net_device *dev = pAd->net_dev; */ /* union iwreq_data wrqu; */ char buf[128]; /* XXX */ /* TODO: needed parameters: count, keyid, key type, src address, TSC */ if(report)/*station reports a mic error to this ap. */ { snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag, keyix, "uni", ether_sprintf(pHeader->Addr2)); } else/*ap itself receives a mic error. */ { snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag, keyix, IEEE80211_IS_MULTICAST(pHeader->Addr1) ? "broad" : "uni", ether_sprintf(pHeader->Addr2)); } RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, -1, NULL, NULL, 0); /* memset(&wrqu, 0, sizeof(wrqu)); */ /* wrqu.data.length = strlen(buf); */ /* wireless_send_event(dev, RT_WLAN_EVENT_CUSTOM, &wrqu, buf); */ }
/* * Add privacy headers appropriate for the specified key. */ struct ieee80211_key * ieee80211_crypto_encap(struct ieee80211com *ic, struct ieee80211_node *ni, struct mbuf *m) { struct ieee80211_key *k; struct ieee80211_frame *wh; const struct ieee80211_cipher *cip; u_int8_t keyid; /* * Multicast traffic always uses the multicast key. * Otherwise if a unicast key is set we use that and * it is always key index 0. When no unicast key is * set we fall back to the default transmit key. */ wh = mtod(m, struct ieee80211_frame *); if (IEEE80211_IS_MULTICAST(wh->i_addr1) || ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, "[%s] no default transmit key (%s) deftxkey %u\n", ether_sprintf(wh->i_addr1), __func__, ic->ic_def_txkey); ic->ic_stats.is_tx_nodefkey++; return NULL; } keyid = ic->ic_def_txkey; k = &ic->ic_nw_keys[ic->ic_def_txkey]; } else { keyid = 0; k = &ni->ni_ucastkey; } cip = k->wk_cipher; return (cip->ic_encap(k, m, keyid<<6) ? k : NULL); }
struct ieee80211_key * ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; /* * Multicast traffic always uses the multicast key. * Otherwise if a unicast key is set we use that and * it is always key index 0. When no unicast key is * set we fall back to the default transmit key. */ wh = mtod(m, struct ieee80211_frame *); if (IEEE80211_IS_MULTICAST(wh->i_addr1) || IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) { if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "no default transmit key (%s) deftxkey %u", __func__, vap->iv_def_txkey); vap->iv_stats.is_tx_nodefkey++; return NULL; } return &vap->iv_nw_keys[vap->iv_def_txkey]; } return &ni->ni_ucastkey; }
void ath_ald_update_frame_stats(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts) { struct ieee80211_frame *wh; int type; int bfUsed = 0; u_int32_t ptime = 0; u_int32_t airtime = 0; int i; void *ds = bf->bf_lastbf->bf_desc; wh = (struct ieee80211_frame *)wbuf_header(bf->bf_mpdu); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; if((type == IEEE80211_FC0_TYPE_DATA) && (!IEEE80211_IS_MULTICAST(wh->i_addr1)) && (!IEEE80211_IS_BROADCAST(wh->i_addr1))){ for(i=0; i < HAL_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { bfUsed += sc->sc_txq[i].axq_num_buf_used; } } ptime = sc->sc_ald.sc_ald_txairtime; airtime = ath_hal_txcalcairtime(sc->sc_ah, ds, ts, AH_FALSE, 1, 1); sc->sc_ald.sc_ald_txairtime += airtime; if (ptime > sc->sc_ald.sc_ald_txairtime) { sc->sc_ald.sc_ald_txairtime = airtime; sc->sc_ald.sc_ald_pktnum = 0; } if (airtime) { sc->sc_ald.sc_ald_pktlen += (bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen); sc->sc_ald.sc_ald_pktnum += bf->bf_nframes; sc->sc_ald.sc_ald_bfused += bfUsed; sc->sc_ald.sc_ald_counter += 1; } } }
/* * Add privacy headers appropriate for the specified key. */ struct ieee80211_key * ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k; struct ieee80211_frame *wh; const struct ieee80211_cipher *cip; uint8_t keyid; /* * Multicast traffic always uses the multicast key. * Otherwise if a unicast key is set we use that and * it is always key index 0. When no unicast key is * set we fall back to the default transmit key. */ wh = mtod(m, struct ieee80211_frame *); if (IEEE80211_IS_MULTICAST(wh->i_addr1) || IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) { if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "no default transmit key (%s) deftxkey %u", __func__, vap->iv_def_txkey); vap->iv_stats.is_tx_nodefkey++; return NULL; } keyid = vap->iv_def_txkey; k = &vap->iv_nw_keys[vap->iv_def_txkey]; } else { keyid = 0; k = &ni->ni_ucastkey; } cip = k->wk_cipher; return (cip->ic_encap(k, m, keyid<<6) ? k : NULL); }
void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent) { #ifdef CONFIG_PM if (ar->arWowState!=WOW_STATE_NONE) { if (ar->arWowState==WOW_STATE_SUSPENDING) { AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s: Received IRQ while we are wow suspending!!!\n", __func__)); return; } /* Wow resume from irq interrupt */ AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arOsPowerCtrl)); ar6000_wow_resume(ar); ar->arOsPowerCtrl = WLAN_PWR_CTRL_UP; } else if (screen_is_off && skb && ar->arConnected) { A_BOOL needWake = FALSE; if (isEvent) { if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) { A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb); switch (cmd) { case WMI_CONNECT_EVENTID: case WMI_DISCONNECT_EVENTID: needWake = TRUE; break; default: /* dont wake lock the system for other event */ break; } } } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) { ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); if (!IEEE80211_IS_MULTICAST(datap->dstMac)) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ case 0x888e: /* EAPOL */ case 0x88c7: /* RSN_PREAUTH */ case 0x88b4: /* WAPI */ needWake = TRUE; break; case 0x0806: /* ARP is not important to hold wake lock */ default: break; } } } if (needWake) { /* keep host wake up if there is any event and packate comming in*/ wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ); if (wowledon) { char buf[32]; int len = sprintf(buf, "on"); android_readwrite_file("/sys/power/state", NULL, buf, len); len = sprintf(buf, "%d", 127); android_readwrite_file("/sys/class/leds/lcd-backlight/brightness", NULL, buf,len); } } } #endif /* CONFIG_PM */ }
/* * Validate and strip privacy headers (and trailer) for a * received frame that has the WEP/Privacy bit set. */ int ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen, struct ieee80211_key **key) { #define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN) #define IEEE80211_WEP_MINLEN \ (sizeof(struct ieee80211_frame) + \ IEEE80211_WEP_HDRLEN + IEEE80211_WEP_CRCLEN) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k; struct ieee80211_frame *wh; const struct ieee80211_rx_stats *rxs; const struct ieee80211_cipher *cip; uint8_t keyid; /* * Check for hardware decryption and IV stripping. * If the IV is stripped then we definitely can't find a key. * Set the key to NULL but return true; upper layers * will need to handle a NULL key for a successful * decrypt. */ rxs = ieee80211_get_rx_params_ptr(m); if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) { if (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP) { /* * Hardware decrypted, IV stripped. * We can't find a key with a stripped IV. * Return successful. */ *key = NULL; return (1); } } /* NB: this minimum size data frame could be bigger */ if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, "%s: WEP data frame too short, len %u\n", __func__, m->m_pkthdr.len); vap->iv_stats.is_rx_tooshort++; /* XXX need unique stat? */ *key = NULL; return (0); } /* * Locate the key. If unicast and there is no unicast * key then we fall back to the key id in the header. * This assumes unicast keys are only configured when * the key id in the header is meaningless (typically 0). */ wh = mtod(m, struct ieee80211_frame *); m_copydata(m, hdrlen + IEEE80211_WEP_IVLEN, sizeof(keyid), &keyid); if (IEEE80211_IS_MULTICAST(wh->i_addr1) || IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) k = &vap->iv_nw_keys[keyid >> 6]; else
struct ieee80211_key *ieee80211_get_txkey(struct ieee80211_s *ic, const struct ieee80211_frame *wh, struct ieee80211_node *ni) { int kid; if ((ic->ic_flags & IEEE80211_F_RSNON) && !IEEE80211_IS_MULTICAST(wh->i_addr1) && ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) return &ni->ni_pairwise_key; if (!IEEE80211_IS_MULTICAST(wh->i_addr1) || (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT) kid = ic->ic_def_txkey; else kid = ic->ic_igtk_kid; return &ic->ic_nw_keys[kid]; }
void r12a_fill_tx_desc_raw(struct rtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m, void *buf, const struct ieee80211_bpf_params *params) { struct ieee80211vap *vap = ni->ni_vap; struct rtwn_vap *uvp = RTWN_VAP(vap); struct ieee80211_frame *wh; struct r12a_tx_desc *txd; uint8_t ridx; int ismcast; /* XXX TODO: 11n checks, matching rtwn_fill_tx_desc() */ wh = mtod(m, struct ieee80211_frame *); ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); ridx = rate2ridx(params->ibp_rate0); /* Fill Tx descriptor. */ txd = (struct r12a_tx_desc *)buf; txd->flags0 |= R12A_FLAGS0_LSG | R12A_FLAGS0_FSG; if (ismcast) txd->flags0 |= R12A_FLAGS0_BMCAST; if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) { txd->txdw4 = htole32(R12A_TXDW4_RETRY_LMT_ENA); txd->txdw4 |= htole32(SM(R12A_TXDW4_RETRY_LMT, params->ibp_try0)); } if (params->ibp_flags & IEEE80211_BPF_RTS) r12a_tx_protection(sc, txd, IEEE80211_PROT_RTSCTS, ridx); if (params->ibp_flags & IEEE80211_BPF_CTS) r12a_tx_protection(sc, txd, IEEE80211_PROT_CTSONLY, ridx); txd->txdw1 |= htole32(SM(R12A_TXDW1_MACID, RTWN_MACID_BC)); txd->txdw1 |= htole32(SM(R12A_TXDW1_QSEL, R12A_TXDW1_QSEL_MGNT)); /* Set TX rate index. */ txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE, ridx)); txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE_FB_LMT, 0x1f)); txd->txdw6 |= htole32(SM(R21A_TXDW6_MBSSID, uvp->id)); txd->txdw3 |= htole32(R12A_TXDW3_DRVRATE); r12a_tx_raid(sc, txd, ni, ismcast); if (!IEEE80211_QOS_HAS_SEQ(wh)) { /* Use HW sequence numbering for non-QoS frames. */ txd->txdw8 |= htole32(R12A_TXDW8_HWSEQ_EN); txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, uvp->id)); } else { /* Set sequence number. */ txd->txdw9 |= htole32(SM(R12A_TXDW9_SEQ, M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE)); } }
struct iob_s *ieee80211_decrypt(FAR struct ieee80211_s *ic, FAR struct iob_s *iob0, struct ieee80211_node *ni) { FAR struct ieee80211_frame *wh; FAR struct ieee80211_key *k; FAR uint8_t *ivp; FAR uint8_t *mmie; uint16_t kid; int hdrlen; /* Find key for decryption */ wh = (FAR struct ieee80211_frame *)IOB_DATA(iob0); if ((ic->ic_flags & IEEE80211_F_RSNON) && !IEEE80211_IS_MULTICAST(wh->i_addr1) && ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) { k = &ni->ni_pairwise_key; } else if (!IEEE80211_IS_MULTICAST(wh->i_addr1) || (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT) { /* Retrieve group data key id from IV field */ hdrlen = ieee80211_get_hdrlen(wh); /* Check that IV field is present */ if (iob0->io_len < hdrlen + 4) { iob_free_chain(iob0); return NULL; } ivp = (uint8_t *) wh + hdrlen; kid = ivp[3] >> 6; k = &ic->ic_nw_keys[kid]; }
/* * Return a reference to the appropriate node for sending * a data frame. This handles node discovery in adhoc networks. * * Drivers will call this, so increase the reference count before * returning the node. */ struct ieee80211_node * ieee80211_find_txnode(struct ieee80211com *ic, const u_int8_t *macaddr) { #ifndef IEEE80211_STA_ONLY struct ieee80211_node *ni; int s; #endif /* * The destination address should be in the node table * unless we are operating in station mode or this is a * multicast/broadcast frame. */ if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr)) return ieee80211_ref_node(ic->ic_bss); #ifndef IEEE80211_STA_ONLY s = splnet(); ni = ieee80211_find_node(ic, macaddr); splx(s); if (ni == NULL) { if (ic->ic_opmode != IEEE80211_M_IBSS && ic->ic_opmode != IEEE80211_M_AHDEMO) return NULL; /* * Fake up a node; this handles node discovery in * adhoc mode. Note that for the driver's benefit * we we treat this like an association so the driver * has an opportunity to setup its private state. * * XXX need better way to handle this; issue probe * request so we can deduce rate set, etc. */ if ((ni = ieee80211_dup_bss(ic, macaddr)) == NULL) return NULL; /* XXX no rate negotiation; just dup */ ni->ni_rates = ic->ic_bss->ni_rates; ni->ni_txrate = 0; if (ic->ic_newassoc) (*ic->ic_newassoc)(ic, ni, 1); } return ieee80211_ref_node(ni); #else return NULL; /* can't get there */ #endif /* IEEE80211_STA_ONLY */ }
/* * Add privacy headers appropriate for the specified key. */ struct ieee80211_key * ieee80211_crypto_encap(struct ieee80211_node *ni, struct sk_buff *skb) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k; struct ieee80211_frame *wh; const struct ieee80211_cipher *cip; u_int8_t keyid; /* * Multicast traffic always uses the multicast key. * Otherwise if a unicast key is set we use that and * it is always key index 0. When no unicast key is * set we fall back to the default transmit key. */ wh = (struct ieee80211_frame *)skb->data; if (IEEE80211_IS_MULTICAST(wh->i_addr1) || ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "no default transmit key (%s) deftxkey %u", __func__, vap->iv_def_txkey); vap->iv_stats.is_tx_nodefkey++; return NULL; } keyid = vap->iv_def_txkey; k = &vap->iv_nw_keys[vap->iv_def_txkey]; } else { keyid = 0; k = &ni->ni_ucastkey; } cip = k->wk_cipher; if (skb_headroom(skb) < cip->ic_header) { /* * Should not happen; ieee80211_skbhdr_adjust should * have allocated enough space for all headers. */ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "%s: malformed packet for cipher %s; headroom %u", __func__, cip->ic_name, skb_headroom(skb)); vap->iv_stats.is_tx_noheadroom++; return NULL; } return (cip->ic_encap(k, skb, keyid << 6) ? k : NULL); }
/* * Add privacy headers appropriate for the specified key. */ struct ieee80211_key * ieee80211_crypto_encap(struct ieee80211com *ic, struct ieee80211_node *ni, struct sk_buff *skb) { struct ieee80211_key *k; struct ieee80211_frame *wh; const struct ieee80211_cipher *cip; u_int8_t keyix; /* * Multicast traffic always uses the multicast key. * Otherwise if a unicast key is set we use that and * it is always key index 0. When no unicast key is * set we fall back to the default transmit key. */ wh = (struct ieee80211_frame *)skb->data; if (IEEE80211_IS_MULTICAST(wh->i_addr1) || ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, ("%s: No default xmit key for frame to %s\n", __func__, ether_sprintf(wh->i_addr1))); ic->ic_stats.is_tx_nodefkey++; return NULL; } keyix = ic->ic_def_txkey; k = &ic->ic_nw_keys[ic->ic_def_txkey]; } else { keyix = 0; k = &ni->ni_ucastkey; } cip = k->wk_cipher; if (skb_headroom(skb) < cip->ic_header) { /* * Should not happen; ieee80211_skbhdr_adjust should * have allocated enough space for all headers. */ IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO, ("%s: Malformed packet for cipher %s; headroom %u\n", __func__, cip->ic_name, skb_headroom(skb))); ic->ic_stats.is_tx_noheadroom++; return NULL; } return ((*cip->ic_encap)(k, skb, keyix<<6) ? k : NULL); }
void host_htc_eptx_comp(void *context, wbuf_t skb, HTC_ENDPOINT_ID epid) { /* for HTC, since we don't have the "real" tx-status, we do them here. */ struct ath_softc_net80211 *scn = (struct ath_softc_net80211 *)context; ath_dev_t sc_dev = scn->sc_dev; struct ath_softc *sc = ATH_DEV_TO_SC(sc_dev); u_int16_t min_len_req_by_stats = sizeof(ath_data_hdr_t)+sizeof(struct ieee80211_frame); if( wbuf_get_pktlen(skb)> min_len_req_by_stats && wbuf_get_tid(skb) < ATH_HTC_WME_NUM_TID &&( epid == sc->sc_data_BE_ep || epid == sc->sc_data_BK_ep || epid == sc->sc_data_VI_ep || epid == sc->sc_data_VO_ep )){ struct ieee80211_node *ni = wbuf_get_node(skb); struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; struct ieee80211_tx_status ts; struct ieee80211_mac_stats *mac_stats; u_int8_t type, subtype; u_int8_t is_mcast; wh = (struct ieee80211_frame *)(wbuf_header(skb)+sizeof(ath_data_hdr_t)); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; /* we fake ts becuase we don't have ts in HTC tx */ ts.ts_flags = 0; ts.ts_retries = 0; ieee80211_update_stats(vap, skb, wh, type, subtype, &ts); /* patch: HTC tx only ath_data_hdr length */ is_mcast = IEEE80211_IS_MULTICAST(wh->i_addr1) ? 1 : 0; mac_stats = is_mcast ? &vap->iv_multicast_stats : &vap->iv_unicast_stats; mac_stats->ims_tx_bytes -= sizeof(ath_data_hdr_t); } ieee80211_free_node(wbuf_get_node(skb)); }
/* * Return a reference to the appropriate node for sending * a data frame. This handles node discovery in adhoc networks. * * Drivers will call this, so increase the reference count before * returning the node. */ struct ieee80211_node * ieee80211_find_txnode(struct ieee80211com *ic, u_int8_t *macaddr) { struct ieee80211_node *ni; /* * The destination address should be in the node table * unless we are operating in station mode or this is a * multicast/broadcast frame. */ if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr)) return ieee80211_ref_node(ic->ic_bss); /* XXX can't hold lock across dup_bss 'cuz of recursive locking */ IEEE80211_NODE_LOCK(ic); ni = ieee80211_find_node(ic, macaddr); IEEE80211_NODE_UNLOCK(ic); if (ni == NULL) { if (ic->ic_opmode != IEEE80211_M_IBSS && ic->ic_opmode != IEEE80211_M_AHDEMO) return NULL; /* * Fake up a node; this handles node discovery in * adhoc mode. Note that for the driver's benefit * we we treat this like an association so the driver * has an opportunity to setup its private state. * * XXX need better way to handle this; issue probe * request so we can deduce rate set, etc. */ if ((ni = ieee80211_dup_bss(ic, macaddr)) == NULL) return NULL; /* XXX no rate negotiation; just dup */ ni->ni_rates = ic->ic_bss->ni_rates; if (ic->ic_newassoc) (*ic->ic_newassoc)(ic, ni, 1); } return ieee80211_ref_node(ni); }
static void wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) { struct bsd_driver_data *drv = sock_ctx; char *buf; struct if_announcemsghdr *ifan; struct if_msghdr *ifm; struct rt_msghdr *rtm; union wpa_event_data event; struct ieee80211_michael_event *mic; struct ieee80211_leave_event *leave; struct ieee80211_join_event *join; int n, len; len = rtbuf_len(); buf = os_malloc(len); if (buf == NULL) { wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__); return; } n = read(sock, buf, len); if (n < 0) { if (errno != EINTR && errno != EAGAIN) wpa_printf(MSG_ERROR, "%s read() failed: %s\n", __func__, strerror(errno)); os_free(buf); return; } rtm = (struct rt_msghdr *) buf; if (rtm->rtm_version != RTM_VERSION) { wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", rtm->rtm_version); os_free(buf); return; } os_memset(&event, 0, sizeof(event)); switch (rtm->rtm_type) { case RTM_IFANNOUNCE: ifan = (struct if_announcemsghdr *) rtm; if (ifan->ifan_index != drv->ifindex) break; os_strlcpy(event.interface_status.ifname, drv->ifname, sizeof(event.interface_status.ifname)); switch (ifan->ifan_what) { case IFAN_DEPARTURE: event.interface_status.ievent = EVENT_INTERFACE_REMOVED; default: os_free(buf); return; } wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", event.interface_status.ifname, ifan->ifan_what == IFAN_DEPARTURE ? "removed" : "added"); wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); break; case RTM_IEEE80211: ifan = (struct if_announcemsghdr *) rtm; if (ifan->ifan_index != drv->ifindex) break; switch (ifan->ifan_what) { case RTM_IEEE80211_ASSOC: case RTM_IEEE80211_REASSOC: if (drv->is_ap) break; wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); break; case RTM_IEEE80211_DISASSOC: if (drv->is_ap) break; wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); break; case RTM_IEEE80211_SCAN: if (drv->is_ap) break; wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL); break; case RTM_IEEE80211_LEAVE: leave = (struct ieee80211_leave_event *) &ifan[1]; drv_event_disassoc(ctx, leave->iev_addr); break; case RTM_IEEE80211_JOIN: #ifdef RTM_IEEE80211_REJOIN case RTM_IEEE80211_REJOIN: #endif join = (struct ieee80211_join_event *) &ifan[1]; bsd_new_sta(drv, ctx, join->iev_addr); break; case RTM_IEEE80211_REPLAY: /* ignore */ break; case RTM_IEEE80211_MICHAEL: mic = (struct ieee80211_michael_event *) &ifan[1]; wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " "keyix=%u src_addr=" MACSTR, mic->iev_keyix, MAC2STR(mic->iev_src)); os_memset(&event, 0, sizeof(event)); event.michael_mic_failure.unicast = !IEEE80211_IS_MULTICAST(mic->iev_dst); wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &event); break; } break; case RTM_IFINFO: ifm = (struct if_msghdr *) rtm; if (ifm->ifm_index != drv->ifindex) break; if ((rtm->rtm_flags & RTF_UP) == 0) { os_strlcpy(event.interface_status.ifname, drv->ifname, sizeof(event.interface_status.ifname)); event.interface_status.ievent = EVENT_INTERFACE_REMOVED; wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", event.interface_status.ifname); wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); } break; } os_free(buf); }
void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent) { #ifdef CONFIG_HAS_WAKELOCK unsigned long wake_timeout = HZ; /* 1 second for normal window's ping test */ #endif AR_SOFTC_DEV_T *arPriv; A_UINT8 i; A_BOOL needWake = FALSE; for(i = 0; i < num_device; i++) { arPriv = ar->arDev[i]; if ( #ifdef CONFIG_HAS_EARLYSUSPEND screen_is_off && #endif skb && arPriv->arConnected) { if (isEvent) { if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) { A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb); switch (cmd) { case WMI_CONNECT_EVENTID: #ifdef CONFIG_HAS_WAKELOCK wake_timeout = 3*HZ; #endif needWake = TRUE; break; default: /* dont wake lock the system for other event */ break; } } } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) { ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); if (!IEEE80211_IS_MULTICAST(datap->dstMac)) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ if (A_NETBUF_LEN(skb)>=24 && *((A_UCHAR*)A_NETBUF_DATA(skb)+23)==0x11) { A_UCHAR *udpPkt = (A_UCHAR*)A_NETBUF_DATA(skb)+14; A_UINT8 ihl = (*udpPkt & 0x0f) * sizeof(A_UINT32); const A_UCHAR ipsec_keepalive[] = { 0x11, 0x94, 0x11, 0x94, 0x00, 0x09, 0x00, 0x00, 0xff }; udpPkt += ihl; if (A_NETBUF_LEN(skb)>=14+ihl+sizeof(ipsec_keepalive) && !memcmp(udpPkt, ipsec_keepalive, sizeof(ipsec_keepalive)-3) && udpPkt[8]==0xff) { /* * RFC 3948 UDP Encapsulation of IPsec ESP Packets * Source and Destination port must be 4500 * Receivers MUST NOT depend upon the UDP checksum being zero * Sender must use 1 byte payload with 0xff * Receiver SHOULD ignore a received NAT-keepalive packet * * IPSec over UDP NAT keepalive packet. Just ignore */ break; } } case 0x888e: /* EAPOL */ case 0x88c7: /* RSN_PREAUTH */ case 0x88b4: /* WAPI */ needWake = TRUE; break; case 0x0806: /* ARP is not important to hold wake lock */ needWake = (arPriv->arNetworkType==AP_NETWORK); break; default: break; } } else if ( !IEEE80211_IS_BROADCAST(datap->dstMac) ) { if (A_NETBUF_LEN(skb)>=14+20 ) { /* check if it is mDNS packets */ A_UINT8 *dstIpAddr = (A_UINT8*)(A_NETBUF_DATA(skb)+14+20-4); struct net_device *ndev = arPriv->arNetDev; needWake = ((dstIpAddr[3] & 0xf8) == 0xf8) && (arPriv->arNetworkType==AP_NETWORK || (ndev->flags & IFF_ALLMULTI || ndev->flags & IFF_MULTICAST)); } }else if (arPriv->arNetworkType==AP_NETWORK) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ if (A_NETBUF_LEN(skb)>=14+20+2) { A_UINT16 dstPort = *(A_UINT16*)(A_NETBUF_DATA(skb)+14+20); dstPort = A_BE2CPU16(dstPort); needWake = (dstPort == 0x43); /* dhcp request */ } break; case 0x0806: needWake = TRUE; default: break; } } } } } if (needWake) { #ifdef CONFIG_HAS_WAKELOCK /* keep host wake up if there is any event and packate comming in*/ wake_lock_timeout(&ar6k_wow_wake_lock, wake_timeout); #endif if (wowledon) { char buf[32]; int len = sprintf(buf, "on"); android_readwrite_file("/sys/power/state", NULL, buf, len); len = sprintf(buf, "%d", 127); android_readwrite_file("/sys/class/leds/lcd-backlight/brightness", NULL, buf,len); } } }
static int ieee80211_mgmt_output(struct ieee80211_s *ic, struct ieee80211_node *ni, struct iob_s *iob, int type) { struct ieee80211_frame *wh; int error; DEBUGASSERT(ni != NULL); ni->ni_inact = 0; /* We want to pass the node down to the driver's start routine. We could * stick this in an m_tag and tack that on to the buffer. However that's * rather expensive to do for every frame so instead we stuff it in a special * pkthdr field. */ error = iob_contig(iob, sizeof(struct ieee80211_frame)); if (error < 0) { ndbg("ERROR: Failed to make contiguous: %d\n", error); return error; } #warning REVISIT: We do not want to burden everty IOB with this information //iob->io_priv = ni; wh = (FAR struct ieee80211_frame *)IOB_DATA(iob); wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type; wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; *(uint16_t *) & wh->i_dur[0] = 0; *(uint16_t *) & wh->i_seq[0] = htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); ni->ni_txseq++; IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr); IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr); IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); /* Check if protection is required for this mgmt frame */ if ((ic->ic_caps & IEEE80211_C_MFP) && (type == IEEE80211_FC0_SUBTYPE_DISASSOC || type == IEEE80211_FC0_SUBTYPE_DEAUTH || type == IEEE80211_FC0_SUBTYPE_ACTION)) { /* Hack: we should not set the Protected bit in outgoing group management * frames, however it is used as an indication to the drivers that they * must encrypt the frame. Drivers should clear this bit from group * management frames (software crypto code will do it). */ if (IEEE80211_IS_MULTICAST(wh->i_addr1) || (ni->ni_flags & IEEE80211_NODE_TXMGMTPROT)) { wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; } } #if defined(CONFIG_DEBUG_NET) && defined (CONFIG_DEBUG_VERBOSE) /* avoid to print too many frames */ if ((type & IEEE80211_FC0_SUBTYPE_MASK) != IEEE80211_FC0_SUBTYPE_PROBE_RESP) { nvdbg("%s: sending %s to %s on channel %u mode %s\n", ic->ic_ifname, ieee80211_mgt_subtype_name[(type & IEEE80211_FC0_SUBTYPE_MASK) >> IEEE80211_FC0_SUBTYPE_SHIFT], ieee80211_addr2str(ni->ni_macaddr), ieee80211_chan2ieee(ic, ni-> ni_chan), ieee80211_phymode_name[ieee80211_chan2mode(ic, ni->ni_chan)]); }
/* * Validate and strip privacy headers (and trailer) for a * received frame. The specified key should be correct but * is also verified. */ static int ccmp_decap(struct ieee80211_key *k, wbuf_t wbuf, int hdrlen, struct ieee80211_rx_status *rs) { struct ccmp_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->cc_vap; struct ieee80211_frame *wh; uint8_t *ivp, *origHdr; u_int64_t pn; u_int8_t tid; struct ieee80211_mac_stats *mac_stats; u_int32_t hwmfp; uint8_t update_keyrsc = 1; /* * Header should have extended IV and sequence number; * verify the former and validate the latter. */ origHdr = (u_int8_t *)wbuf_header(wbuf); wh = (struct ieee80211_frame *)origHdr; mac_stats = IEEE80211_IS_MULTICAST(wh->i_addr1) ? &vap->iv_multicast_stats : &vap->iv_unicast_stats; if (IEEE80211_IS_MFP_FRAME(wh)) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s MFP frame\n", __func__); } if (rs->rs_flags & IEEE80211_RX_DECRYPT_ERROR) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s decrypt error\n", __func__); if (IEEE80211_IS_MFP_FRAME(wh)) { /* It may not be real crypto error, but hardware didn't do correct * decryption. Try software decrypt later. */ rs->rs_flags &= ~IEEE80211_RX_DECRYPT_ERROR; rs->rs_flags |= IEEE80211_RX_MIC_ERROR; } else { /* The frame already failed decryption in hardware, * just update statistics and return. */ mac_stats->ims_rx_ccmpmic++; return 0; } } ivp = origHdr + hdrlen; if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) { /* * No extended IV; discard frame. */ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, "%s", "Missing ExtIV for AES-CCM cipher"); mac_stats->ims_rx_ccmpformat++; return 0; } tid = IEEE80211_NON_QOS_SEQ; if (IEEE80211_QOS_HAS_SEQ(wh)) { if ( (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS ) { tid = ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0] & IEEE80211_QOS_TID; } else { tid = ((struct ieee80211_qosframe *)wh)->i_qos[0] & IEEE80211_QOS_TID; } } /* NB: assume IEEEE80211_WEP_MINLEN covers the extended IV */ pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); if (pn <= k->wk_keyrsc[tid]) { /* * Replay violation. */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: CCMP Replay! Throw away. new pn=0x%x%x, " "current pn=0x%x%x. seq=0x%x,Rsvd=0x%x,keyID=0x%x,tid=%d\n", __func__, (u_int32_t)(pn>>32), (u_int32_t)pn, (u_int32_t)(k->wk_keyrsc[tid] >> 32), (u_int32_t)k->wk_keyrsc[tid], *(u_int16_t*)(wh->i_seq), ivp[2], ivp[3], tid ); ieee80211_notify_replay_failure(vap, wh, k, pn); mac_stats->ims_rx_ccmpreplay++; return 0; }
int iwl_tx_data(struct iwl_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { struct iwl_ops *ops = &sc->ops; const struct ieee80211_txparam *tp; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct iwl_node *wn = (void *)ni; struct iwl_tx_ring *ring; struct iwl_tx_desc *desc; struct iwl_tx_data *data; struct iwl_tx_cmd *cmd; struct iwl_cmd_data *tx; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; struct mbuf *m1; uint32_t flags; uint16_t qos; u_int hdrlen; bus_dma_segment_t *seg, segs[IWL_MAX_SCATTER]; uint8_t tid, ridx, txant, type; int ac, i, totlen, error, pad, nsegs = 0, rate; struct iwl_vap *ivp = IWL_VAP(vap); IWL_LOCK_ASSERT(sc); wh = mtod(m, struct ieee80211_frame *); hdrlen = ieee80211_anyhdrsize(wh); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; /* Select EDCA Access Category and TX ring for this frame. */ if (IEEE80211_QOS_HAS_SEQ(wh)) { qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; tid = qos & IEEE80211_QOS_TID; } else { qos = 0; tid = 0; } if(ivp->ctx == IWL_RXON_PAN_CTX) ac = iwl_pan_ac_to_queue[M_WME_GETAC(m)]; else ac = iwl_bss_ac_to_queue[M_WME_GETAC(m)]; if (IEEE80211_QOS_HAS_SEQ(wh) && IEEE80211_AMPDU_RUNNING(&ni->ni_tx_ampdu[ac])) { struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac]; ring = &sc->txq[*(int *)tap->txa_private]; *(uint16_t *)wh->i_seq = htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT); ni->ni_txseqs[tid]++; } else ring = &sc->txq[ac]; desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; /* Choose a TX rate index. */ tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; if (type == IEEE80211_FC0_TYPE_MGT) rate = tp->mgmtrate; else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) rate = tp->mcastrate; else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; else rate = ni->ni_txrate; ridx = ic->ic_rt->rateCodeToIndex[rate]; /* Encrypt the frame if need be. */ if (wh->i_fc[1] & IEEE80211_FC1_WEP) { /* Retrieve key for TX. */ k = ieee80211_crypto_encap(ni, m); if (k == NULL) { m_freem(m); return ENOBUFS; } /* 802.11 header may have moved. */ wh = mtod(m, struct ieee80211_frame *); }
struct ol_tx_frms_queue_t * ol_tx_classify( struct ol_txrx_vdev_t *vdev, struct ol_tx_desc_t *tx_desc, adf_nbuf_t tx_nbuf, struct ol_txrx_msdu_info_t *tx_msdu_info) { struct ol_txrx_pdev_t *pdev = vdev->pdev; struct ol_txrx_peer_t *peer = NULL; struct ol_tx_frms_queue_t *txq = NULL; A_UINT8 *dest_addr; A_UINT8 tid; #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) u_int8_t peer_id; #endif TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); dest_addr = ol_tx_dest_addr_find(pdev, tx_nbuf); if ((IEEE80211_IS_MULTICAST(dest_addr)) || (vdev->opmode == wlan_op_mode_ocb)) { txq = &vdev->txqs[OL_TX_VDEV_MCAST_BCAST]; tx_msdu_info->htt.info.ext_tid = HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST; if (vdev->opmode == wlan_op_mode_sta) { /* * The STA sends a frame with a broadcast dest addr (DA) as a * unicast frame to the AP's receive addr (RA). * Find the peer object that represents the AP that the STA * is associated with. */ peer = ol_txrx_assoc_peer_find(vdev); if (!peer) { VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, "Error: STA %p (%02x:%02x:%02x:%02x:%02x:%02x) " "trying to send bcast DA tx data frame " "w/o association\n", vdev, vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); return NULL; /* error */ } else if ((peer->security[OL_TXRX_PEER_SECURITY_MULTICAST].sec_type != htt_sec_type_wapi) && (A_STATUS_OK == adf_nbuf_is_dhcp_pkt(tx_nbuf))) { /* DHCP frame to go with voice priority */ txq = &peer->txqs[TX_DHCP_TID]; tx_msdu_info->htt.info.ext_tid = TX_DHCP_TID; } /* * The following line assumes each peer object has a single ID. * This is currently true, and is expected to remain true. */ tx_msdu_info->htt.info.peer_id = peer->peer_ids[0]; } else if (vdev->opmode == wlan_op_mode_ocb) { tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID; /* In OCB mode, don't worry about the peer. We don't need it. */ peer = NULL; } else { tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID; /* * Look up the vdev's BSS peer, so that the classify_extension * function can check whether to encrypt multicast / broadcast * frames. */ peer = ol_txrx_peer_find_hash_find(pdev, vdev->mac_addr.raw, 0, 1); if (!peer) { VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, "Error: vdev %p (%02x:%02x:%02x:%02x:%02x:%02x) " "trying to send bcast/mcast, but no self-peer found\n", vdev, vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); return NULL; /* error */ } } tx_msdu_info->htt.info.is_unicast = FALSE; } else { /* tid would be overwritten for non QoS case*/ tid = ol_tx_tid(pdev, tx_nbuf, tx_msdu_info); if ((HTT_TX_EXT_TID_INVALID == tid) || (tid >= OL_TX_NUM_TIDS)) { VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, "%s Error: could not classify packet into valid TID(%d).\n", __func__, tid); return NULL; } #ifdef ATH_SUPPORT_WAPI /* Check to see if a frame is a WAI frame */ if (tx_msdu_info->htt.info.ethertype == ETHERTYPE_WAI) { /* WAI frames should not be encrypted */ tx_msdu_info->htt.action.do_encrypt = 0; VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, "Tx Frame is a WAI frame\n"); } #endif /* ATH_SUPPORT_WAPI */ /* * Find the peer and increment its reference count. * If this vdev is an AP, use the dest addr (DA) to determine * which peer STA this unicast data frame is for. * If this vdev is a STA, the unicast data frame is for the * AP the STA is associated with. */ if (vdev->opmode == wlan_op_mode_sta) { /* * TO DO: * To support TDLS, first check if there is a TDLS peer STA, * and if so, check if the DA matches the TDLS peer STA's * MAC address. * If there is no peer TDLS STA, or if the DA is not the * TDLS STA's address, then the frame is either for the AP * itself, or is supposed to be sent to the AP for forwarding. */ #if 0 if (vdev->num_tdls_peers > 0) { peer = NULL; for (i = 0; i < vdev->num_tdls_peers); i++) { int differs = adf_os_mem_cmp( vdev->tdls_peers[i]->mac_addr.raw, dest_addr, OL_TXRX_MAC_ADDR_LEN); if (!differs) { peer = vdev->tdls_peers[i]; break; } } } else { /* send to AP */ peer = ol_txrx_assoc_peer_find(vdev); } #endif #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) if (vdev->hlTdlsFlag) { peer = ol_txrx_find_peer_by_addr(pdev, vdev->hl_tdls_ap_mac_addr.raw, &peer_id); if (peer && (peer->peer_ids[0] == HTT_INVALID_PEER_ID)) peer = NULL; else { if (peer) adf_os_atomic_inc(&peer->ref_cnt); } } if (!peer) peer = ol_txrx_assoc_peer_find(vdev); #else peer = ol_txrx_assoc_peer_find(vdev); #endif } else {
static int hwmp_send_action(struct ieee80211_node *ni, const uint8_t sa[IEEE80211_ADDR_LEN], const uint8_t da[IEEE80211_ADDR_LEN], uint8_t *ie, size_t len) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct ieee80211_bpf_params params; struct mbuf *m; uint8_t *frm; #ifdef IEEE80211_DEBUG_REFCNT char ethstr[ETHER_ADDRSTRLEN + 1]; #endif if (vap->iv_state == IEEE80211_S_CAC) { IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni, "block %s frame in CAC state", "HWMP action"); vap->iv_stats.is_tx_badstate++; return EIO; /* XXX */ } KASSERT(ni != NULL, ("null node")); /* * Hold a reference on the node so it doesn't go away until after * the xmit is complete all the way in the driver. On error we * will remove our reference. */ #ifdef IEEE80211_DEBUG_REFCNT IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, ni, kether_ntoa(ni->ni_macaddr, ethstr), ieee80211_node_refcnt(ni)+1); #endif ieee80211_ref_node(ni); m = ieee80211_getmgtframe(&frm, ic->ic_headroom + sizeof(struct ieee80211_frame), sizeof(struct ieee80211_action) + len ); if (m == NULL) { ieee80211_free_node(ni); vap->iv_stats.is_tx_nobuf++; return ENOMEM; } *frm++ = IEEE80211_ACTION_CAT_MESHPATH; *frm++ = IEEE80211_ACTION_MESHPATH_SEL; switch (*ie) { case IEEE80211_ELEMID_MESHPREQ: frm = hwmp_add_meshpreq(frm, (struct ieee80211_meshpreq_ie *)ie); break; case IEEE80211_ELEMID_MESHPREP: frm = hwmp_add_meshprep(frm, (struct ieee80211_meshprep_ie *)ie); break; case IEEE80211_ELEMID_MESHPERR: frm = hwmp_add_meshperr(frm, (struct ieee80211_meshperr_ie *)ie); break; case IEEE80211_ELEMID_MESHRANN: frm = hwmp_add_meshrann(frm, (struct ieee80211_meshrann_ie *)ie); break; } m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); M_PREPEND(m, sizeof(struct ieee80211_frame), MB_DONTWAIT); if (m == NULL) { ieee80211_free_node(ni); vap->iv_stats.is_tx_nobuf++; return ENOMEM; } ieee80211_send_setup(ni, m, IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION, IEEE80211_NONQOS_TID, sa, da, sa); m->m_flags |= M_ENCAP; /* mark encapsulated */ IEEE80211_NODE_STAT(ni, tx_mgmt); memset(¶ms, 0, sizeof(params)); params.ibp_pri = WME_AC_VO; params.ibp_rate0 = ni->ni_txparms->mgmtrate; if (IEEE80211_IS_MULTICAST(da)) params.ibp_try0 = 1; else params.ibp_try0 = ni->ni_txparms->maxretry; params.ibp_power = ni->ni_txpower; return ic->ic_raw_xmit(ni, m, ¶ms); }
/* * Context: softIRQ (tasklet) */ void ieee80211_input_monitor(struct ieee80211com *ic, struct sk_buff *skb, const struct ath_buf *bf, int tx, u_int64_t mactime, struct ath_softc *sc) { struct ieee80211vap *vap, *next; struct ath_desc *ds = bf->bf_desc; int noise = 0, antenna = 0, ieeerate = 0; u_int32_t rssi = 0; u_int8_t pkttype = 0; unsigned int mon_hdrspace = A_MAX(sizeof(struct ath_tx_radiotap_header), (A_MAX(sizeof(struct wlan_ng_prism2_header), ATHDESC_HEADER_SIZE))); if ((skb_headroom(skb) < mon_hdrspace) && pskb_expand_head(skb, mon_hdrspace, 0, GFP_ATOMIC)) { printk("No headroom for monitor header - %s:%d %s\n", __FILE__, __LINE__, __func__); return; } if (tx) { rssi = bf->bf_dsstatus.ds_txstat.ts_rssi; antenna = bf->bf_dsstatus.ds_txstat.ts_antenna; ieeerate = sc->sc_hwmap[bf->bf_dsstatus.ds_txstat.ts_rate].ieeerate; } else { rssi = bf->bf_dsstatus.ds_rxstat.rs_rssi; antenna = bf->bf_dsstatus.ds_rxstat.rs_antenna; ieeerate = sc->sc_hwmap[bf->bf_dsstatus.ds_rxstat.rs_rate].ieeerate; } noise = bf->bf_channoise; /* XXX locking */ for (vap = TAILQ_FIRST(&ic->ic_vaps); vap != NULL; vap = next) { struct sk_buff *skb1; struct net_device *dev = vap->iv_dev; struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data; u_int8_t dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; next = TAILQ_NEXT(vap, iv_next); /* If we have rx'd an error frame... */ if (!tx && bf->bf_dsstatus.ds_rxstat.rs_status != 0) { /* Discard PHY errors if necessary */ if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_PHY) { if (vap->iv_monitor_phy_errors == 0) continue; } /* Discard CRC errors if necessary */ if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_CRC) { if (vap->iv_monitor_crc_errors == 0) continue; } /* Accept PHY, CRC and decrypt errors. Discard the rest. */ if (bf->bf_dsstatus.ds_rxstat.rs_status &~ (HAL_RXERR_DECRYPT | HAL_RXERR_MIC | HAL_RXERR_PHY | HAL_RXERR_CRC)) continue; /* We can't use addr1 to determine direction at this point */ pkttype = PACKET_HOST; } else { /* * The frame passed its CRC, so we can rely * on the contents of the frame to set pkttype. */ if (tx) pkttype = PACKET_OUTGOING; else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { if (IEEE80211_ADDR_EQ(wh->i_addr1, dev->broadcast)) pkttype = PACKET_BROADCAST; else pkttype = PACKET_MULTICAST; } else pkttype = PACKET_HOST; } if (vap->iv_opmode != IEEE80211_M_MONITOR || vap->iv_state != IEEE80211_S_RUN) continue; if (vap->iv_monitor_nods_only && dir != IEEE80211_FC1_DIR_NODS) { /* don't rx fromds, tods, or dstods packets */ continue; } skb1 = skb_copy(skb, GFP_ATOMIC); if (skb1 == NULL) { /* XXX stat+msg */ continue; } ieee80211_skb_copy_noderef(skb, skb1); if (vap->iv_monitor_txf_len && tx) { /* truncate transmit feedback packets */ skb_trim(skb1, vap->iv_monitor_txf_len); skb_reset_network_header(skb1); } switch (vap->iv_dev->type) { case ARPHRD_IEEE80211: break; case ARPHRD_IEEE80211_PRISM: { struct wlan_ng_prism2_header *ph; if (skb_headroom(skb1) < sizeof(struct wlan_ng_prism2_header)) { ieee80211_dev_kfree_skb(&skb1); break; } ph = (struct wlan_ng_prism2_header *) skb_push(skb1, sizeof(struct wlan_ng_prism2_header)); memset(ph, 0, sizeof(struct wlan_ng_prism2_header)); ph->msgcode = DIDmsg_lnxind_wlansniffrm; ph->msglen = sizeof(struct wlan_ng_prism2_header); strncpy(ph->devname, dev->name, sizeof(ph->devname)); ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; ph->hosttime.status = 0; ph->hosttime.len = 4; ph->hosttime.data = jiffies; /* Pass up tsf clock in mactime */ /* NB: the prism mactime field is 32bit, so we lose TSF precision here */ ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; ph->mactime.status = 0; ph->mactime.len = 4; ph->mactime.data = mactime; ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; ph->istx.status = 0; ph->istx.len = 4; ph->istx.data = tx ? P80211ENUM_truth_true : P80211ENUM_truth_false; ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; ph->frmlen.status = 0; ph->frmlen.len = 4; ph->frmlen.data = skb->len; ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; ph->channel.status = 0; ph->channel.len = 4; ph->channel.data = ieee80211_mhz2ieee(ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags); ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; ph->rssi.status = 0; ph->rssi.len = 4; ph->rssi.data = rssi; ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; ph->noise.status = 0; ph->noise.len = 4; ph->noise.data = noise; ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; ph->signal.status = 0; ph->signal.len = 4; ph->signal.data = rssi + noise; ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; ph->rate.status = 0; ph->rate.len = 4; ph->rate.data = ieeerate; break; } case ARPHRD_IEEE80211_RADIOTAP: { if (tx) { struct ath_tx_radiotap_header *th; if (skb_headroom(skb1) < sizeof(struct ath_tx_radiotap_header)) { printk("%s:%d %s\n", __FILE__, __LINE__, __func__); ieee80211_dev_kfree_skb(&skb1); break; } th = (struct ath_tx_radiotap_header *) skb_push(skb1, sizeof(struct ath_tx_radiotap_header)); memset(th, 0, sizeof(struct ath_tx_radiotap_header)); th->wt_ihdr.it_version = 0; th->wt_ihdr.it_len = cpu_to_le16(sizeof(struct ath_tx_radiotap_header)); th->wt_ihdr.it_present = cpu_to_le32(ATH_TX_RADIOTAP_PRESENT); /* radiotap's TSF field is the full 64 bits, so we don't lose * any TSF precision when using radiotap */ th->wt_tsft = cpu_to_le64(mactime); th->wt_flags = 0; th->wt_rate = ieeerate; th->wt_antenna = antenna; th->wt_pad = 0; if (bf->bf_dsstatus.ds_txstat.ts_status & HAL_TXERR_XRETRY) th->wt_txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); th->wt_dataretries = bf->bf_dsstatus.ds_txstat.ts_shortretry + bf->bf_dsstatus.ds_txstat.ts_longretry; } else { struct ath_rx_radiotap_header *th; if (skb_headroom(skb1) < sizeof(struct ath_rx_radiotap_header)) { printk("%s:%d %s\n", __FILE__, __LINE__, __func__); ieee80211_dev_kfree_skb(&skb1); break; } th = (struct ath_rx_radiotap_header *) skb_push(skb1, sizeof(struct ath_rx_radiotap_header)); memset(th, 0, sizeof(struct ath_rx_radiotap_header)); th->wr_ihdr.it_version = 0; th->wr_ihdr.it_len = cpu_to_le16(sizeof(struct ath_rx_radiotap_header)); th->wr_ihdr.it_present = cpu_to_le32(ATH_RX_RADIOTAP_PRESENT); if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) th->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_CRC) th->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; if (skb->len >= IEEE80211_CRC_LEN) th->wr_flags |= IEEE80211_RADIOTAP_F_FCS; th->wr_rate = ieeerate; th->wr_chan_freq = cpu_to_le16(ic->ic_curchan->ic_freq); /* Define the channel flags for radiotap */ switch (sc->sc_curmode) { case IEEE80211_MODE_11A: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_A); break; case IEEE80211_MODE_TURBO_A: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_TA); break; case IEEE80211_MODE_11B: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_B); break; case IEEE80211_MODE_11G: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_G); break; case IEEE80211_MODE_TURBO_G: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_TG); break; default: th->wr_chan_flags = 0; /* unknown */ break; } th->wr_dbm_antnoise = (int8_t) noise; th->wr_dbm_antsignal = th->wr_dbm_antnoise + rssi; th->wr_antenna = antenna; th->wr_antsignal = rssi; th->wr_tsft = cpu_to_le64(mactime); } break; } case ARPHRD_IEEE80211_ATHDESC: { if (skb_headroom(skb1) < ATHDESC_HEADER_SIZE) { printk("%s:%d %s\n", __FILE__, __LINE__, __func__); ieee80211_dev_kfree_skb(&skb1); break; } memcpy(skb_push(skb1, ATHDESC_HEADER_SIZE), ds, ATHDESC_HEADER_SIZE); break; } default: break; } if (skb1 != NULL) { if (!tx && (skb1->len >= IEEE80211_CRC_LEN) && (vap->iv_dev->type != ARPHRD_IEEE80211_RADIOTAP)) { /* Remove FCS from end of RX frames when * delivering to non-Radiotap VAPs. */ skb_trim(skb1, skb1->len - IEEE80211_CRC_LEN); } skb1->dev = dev; /* NB: deliver to wlanX */ skb_reset_mac_header(skb1); skb1->ip_summed = CHECKSUM_NONE; skb1->pkt_type = pkttype; skb1->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ if (netif_rx(skb1) == NET_RX_DROP) { /* If netif_rx dropped the packet because * device was too busy, reclaim the ref. in * the skb. */ if (SKB_CB(skb1)->ni != NULL) ieee80211_unref_node(&SKB_CB(skb1)->ni); vap->iv_devstats.rx_dropped++; } vap->iv_devstats.rx_packets++; vap->iv_devstats.rx_bytes += skb1->len; } } }
void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent) { AR_SOFTC_DEV_T *arPriv; A_UINT8 i; A_BOOL needWake = FALSE; for(i = 0; i < num_device; i++) { arPriv = ar->arDev[i]; if ( #ifdef CONFIG_HAS_EARLYSUSPEND screen_is_off && #endif skb && arPriv->arConnected) { if (isEvent) { if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) { A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb); switch (cmd) { case WMI_CONNECT_EVENTID: case WMI_DISCONNECT_EVENTID: needWake = TRUE; break; default: /* dont wake lock the system for other event */ break; } } } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) { ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); if (!IEEE80211_IS_MULTICAST(datap->dstMac)) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ case 0x888e: /* EAPOL */ case 0x88c7: /* RSN_PREAUTH */ case 0x88b4: /* WAPI */ needWake = TRUE; break; case 0x0806: /* ARP is not important to hold wake lock */ needWake = (arPriv->arNetworkType==AP_NETWORK); break; default: break; } } else if ( !IEEE80211_IS_BROADCAST(datap->dstMac) ) { if (A_NETBUF_LEN(skb)>=14+20 ) { /* check if it is mDNS packets */ A_UINT8 *dstIpAddr = (A_UINT8*)(A_NETBUF_DATA(skb)+14+20-4); struct net_device *ndev = arPriv->arNetDev; needWake = ((dstIpAddr[3] & 0xf8) == 0xf8) && (arPriv->arNetworkType==AP_NETWORK || (ndev->flags & IFF_ALLMULTI || ndev->flags & IFF_MULTICAST)); } }else if (arPriv->arNetworkType==AP_NETWORK) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ if (A_NETBUF_LEN(skb)>=14+20+2) { A_UINT16 dstPort = *(A_UINT16*)(A_NETBUF_DATA(skb)+14+20); dstPort = A_BE2CPU16(dstPort); needWake = (dstPort == 0x43); /* dhcp request */ } break; case 0x0806: needWake = TRUE; default: break; } } } } } if (needWake) { #ifdef CONFIG_HAS_WAKELOCK /* keep host wake up if there is any event and packate comming in*/ wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ); #endif if (wowledon) { char buf[32]; int len = sprintf(buf, "on"); android_readwrite_file("/sys/power/state", NULL, buf, len); len = sprintf(buf, "%d", 127); android_readwrite_file("/sys/class/leds/lcd-backlight/brightness", NULL, buf,len); } } }
int ieee80211_recv_probereq(struct ieee80211_node *ni, wbuf_t wbuf, int subtype) { struct ieee80211com *ic = ni->ni_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; u_int8_t *frm, *efrm; u_int8_t *ssid, *rates, *ven; #if ATH_SUPPORT_AP_WDS_COMBO if (vap->iv_opmode == IEEE80211_M_STA || !ieee80211_vap_ready_is_set(vap) || vap->iv_no_beacon) { #else if (vap->iv_opmode == IEEE80211_M_STA || !ieee80211_vap_ready_is_set(vap)) { #endif vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */ return -EINVAL; } wh = (struct ieee80211_frame *) wbuf_header(wbuf); frm = (u_int8_t *)&wh[1]; efrm = wbuf_header(wbuf) + wbuf_get_pktlen(wbuf); /*zhaoyang1 add start for probe request REQUIREMENTS-340*/ if (vap->iv_probe_request) { switch (vap->iv_probe_request) { case IEEE80211_BROADCAST_PROBE: if (IEEE80211_IS_BROADCAST(wh->i_addr1)) { vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */ return -EINVAL; } break; case IEEE80211_ALL_PROBE: vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */ return -EINVAL; default: printk("Probe_req value is wrong, iv_probe_request = %d\n", vap->iv_probe_request); break; } } /*zhaoyang1 add end*/ if (IEEE80211_IS_MULTICAST(wh->i_addr2)) { /* frame must be directed */ vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */ return -EINVAL; } /* * prreq frame format * [tlv] ssid * [tlv] supported rates * [tlv] extended supported rates * [tlv] Atheros Advanced Capabilities */ ssid = rates = NULL; while (((frm+1) < efrm) && (frm + frm[1] + 1 < efrm)) { switch (*frm) { case IEEE80211_ELEMID_SSID: ssid = frm; break; case IEEE80211_ELEMID_RATES: rates = frm; break; case IEEE80211_ELEMID_VENDOR: if (vap->iv_venie && vap->iv_venie->ven_oui_set) { ven = frm; if (ven[2] == vap->iv_venie->ven_oui[0] && ven[3] == vap->iv_venie->ven_oui[1] && ven[4] == vap->iv_venie->ven_oui[2]) { vap->iv_venie->ven_ie_len = MIN(ven[1] + 2, IEEE80211_MAX_IE_LEN); OS_MEMCPY(vap->iv_venie->ven_ie, ven, vap->iv_venie->ven_ie_len); } } break; } frm += frm[1] + 2; } if (frm > efrm) { return -EINVAL; } IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); IEEE80211_VERIFY_SSID(vap->iv_bss, ssid); if (IEEE80211_VAP_IS_HIDESSID_ENABLED(vap) && (ssid[1] == 0)) { IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, wh, ieee80211_mgt_subtype_name[ subtype >> IEEE80211_FC0_SUBTYPE_SHIFT], "%s", "no ssid with ssid suppression enabled"); vap->iv_stats.is_rx_ssidmismatch++; /*XXX*/ return -EINVAL; } /* * Skip Probe Requests received while the scan algorithm is setting a new * channel, or while in a foreign channel. * Trying to transmit a frame (Probe Response) during a channel change * (which includes a channel reset) can cause a NMI due to invalid HW * addresses. * Trying to transmit the Probe Response while in a foreign channel * wouldn't do us any good either. */ if (ieee80211_scan_can_transmit(ic->ic_scanner)) ieee80211_send_proberesp(ni, wh->i_addr2, NULL,0); return 0; }
static void wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) { struct wpa_driver_bsd_data *drv = sock_ctx; char buf[2048]; struct if_announcemsghdr *ifan; struct if_msghdr *ifm; struct rt_msghdr *rtm; union wpa_event_data event; struct ieee80211_michael_event *mic; int n; n = read(sock, buf, sizeof(buf)); if (n < 0) { if (errno != EINTR && errno != EAGAIN) perror("read(PF_ROUTE)"); return; } rtm = (struct rt_msghdr *) buf; if (rtm->rtm_version != RTM_VERSION) { wpa_printf(MSG_DEBUG, "Routing message version %d not " "understood\n", rtm->rtm_version); return; } memset(&event, 0, sizeof(event)); switch (rtm->rtm_type) { case RTM_IFANNOUNCE: ifan = (struct if_announcemsghdr *) rtm; if (ifan->ifan_index != drv->ifindex) break; strlcpy(event.interface_status.ifname, drv->ifname, sizeof(event.interface_status.ifname)); switch (ifan->ifan_what) { case IFAN_DEPARTURE: event.interface_status.ievent = EVENT_INTERFACE_REMOVED; default: return; } wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", event.interface_status.ifname, ifan->ifan_what == IFAN_DEPARTURE ? "removed" : "added"); wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); break; case RTM_IEEE80211: ifan = (struct if_announcemsghdr *) rtm; if (ifan->ifan_index != drv->ifindex) break; switch (ifan->ifan_what) { case RTM_IEEE80211_ASSOC: case RTM_IEEE80211_REASSOC: wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); break; case RTM_IEEE80211_DISASSOC: wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); break; case RTM_IEEE80211_SCAN: wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL); break; case RTM_IEEE80211_REPLAY: /* ignore */ break; case RTM_IEEE80211_MICHAEL: mic = (struct ieee80211_michael_event *) &ifan[1]; wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " "keyix=%u src_addr=" MACSTR, mic->iev_keyix, MAC2STR(mic->iev_src)); memset(&event, 0, sizeof(event)); event.michael_mic_failure.unicast = !IEEE80211_IS_MULTICAST(mic->iev_dst); wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &event); break; } break; case RTM_IFINFO: ifm = (struct if_msghdr *) rtm; if (ifm->ifm_index != drv->ifindex) break; if ((rtm->rtm_flags & RTF_UP) == 0) { strlcpy(event.interface_status.ifname, drv->ifname, sizeof(event.interface_status.ifname)); event.interface_status.ievent = EVENT_INTERFACE_REMOVED; wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", event.interface_status.ifname); wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); } break; } }
static struct ieee80211_node * hwmp_discover(struct ieee80211vap *vap, const uint8_t dest[IEEE80211_ADDR_LEN], struct mbuf *m) { struct ieee80211_hwmp_state *hs = vap->iv_hwmp; struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ieee80211_mesh_route *rt = NULL; struct ieee80211_hwmp_route *hr; struct ieee80211_meshpreq_ie preq; struct ieee80211_node *ni; int sendpreq = 0; #ifdef IEEE80211_DEBUG char ethstr[ETHER_ADDRSTRLEN + 1]; #endif KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a mesh vap, opmode %d", vap->iv_opmode)); KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest), ("%s: discovering self!", __func__)); ni = NULL; if (!IEEE80211_IS_MULTICAST(dest)) { rt = ieee80211_mesh_rt_find(vap, dest); if (rt == NULL) { rt = ieee80211_mesh_rt_add(vap, dest); if (rt == NULL) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "unable to add discovery path to %s", kether_ntoa(dest, ethstr)); vap->iv_stats.is_mesh_rtaddfailed++; goto done; } } hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { if (hr->hr_origseq == 0) hr->hr_origseq = ++hs->hs_seq; rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL; rt->rt_lifetime = ticks_to_msecs(ieee80211_hwmp_pathtimeout); /* XXX check preq retries */ sendpreq = 1; if (m != NULL) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest, "%s", "start path discovery (src <none>)"); } else { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest, "start path discovery (src %s)", kether_ntoa( mtod(m, struct ether_header *)->ether_shost, ethstr)); } /* * Try to discover the path for this node. */ preq.preq_flags = 0; preq.preq_hopcount = 0; preq.preq_ttl = ms->ms_ttl; preq.preq_id = ++hs->hs_preqid; IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr); preq.preq_origseq = hr->hr_origseq; preq.preq_lifetime = rt->rt_lifetime; preq.preq_metric = rt->rt_metric; preq.preq_tcount = 1; IEEE80211_ADDR_COPY(PREQ_TADDR(0), dest); PREQ_TFLAGS(0) = 0; if (ieee80211_hwmp_targetonly) PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_TO; if (ieee80211_hwmp_replyforward) PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_RF; PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN; PREQ_TSEQ(0) = 0; /* XXX check return value */ hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq); } if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) ni = ieee80211_find_txnode(vap, rt->rt_nexthop); } else {
static int rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m) { const struct ieee80211_txparam *tp; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k = NULL; struct ieee80211_channel *chan; struct ieee80211_frame *wh; struct rtwn_tx_desc_common *txd; struct rtwn_tx_buf buf; uint8_t rate, ridx, type; u_int cipher; int ismcast, maxretry; RTWN_ASSERT_LOCKED(sc); wh = mtod(m, struct ieee80211_frame *); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ? ni->ni_chan : ic->ic_curchan; tp = &vap->iv_txparms[ieee80211_chan2mode(chan)]; maxretry = tp->maxretry; /* Choose a TX rate index. */ if (type == IEEE80211_FC0_TYPE_MGT) rate = tp->mgmtrate; else if (ismcast) rate = tp->mcastrate; else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; else if (m->m_flags & M_EAPOL) rate = tp->mgmtrate; else { if (sc->sc_ratectl == RTWN_RATECTL_NET80211) { /* XXX pass pktlen */ (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } else { if (ni->ni_flags & IEEE80211_NODE_HT) rate = IEEE80211_RATE_MCS | 0x4; /* MCS4 */ else if (ic->ic_curmode != IEEE80211_MODE_11B) rate = ridx2rate[RTWN_RIDX_OFDM36]; else rate = ridx2rate[RTWN_RIDX_CCK55]; } } ridx = rate2ridx(rate); cipher = IEEE80211_CIPHER_NONE; if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m); if (k == NULL) { device_printf(sc->sc_dev, "ieee80211_crypto_encap returns NULL.\n"); return (ENOBUFS); } if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) cipher = k->wk_cipher->ic_cipher; /* in case packet header moved, reset pointer */ wh = mtod(m, struct ieee80211_frame *); }