Exemplo n.º 1
0
/*
 * 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
Exemplo n.º 2
0
/*
 * 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
Exemplo n.º 3
0
/*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); */
}
Exemplo n.º 4
0
/*
 * 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);
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
        }
    }
}
Exemplo n.º 7
0
/*
 * 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);
}
Exemplo n.º 8
0
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 */
}
Exemplo n.º 9
0
/*
 * 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
Exemplo n.º 10
0
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];
}
Exemplo n.º 11
0
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));
	}
}
Exemplo n.º 12
0
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];
    }
Exemplo n.º 13
0
/*
 * 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 */
}
Exemplo n.º 14
0
/*
 * 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);
}
Exemplo n.º 15
0
/*
 * 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);
}
Exemplo n.º 16
0
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));
}
Exemplo n.º 17
0
/*
 * 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);
}
Exemplo n.º 19
0
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);
        }
    }
}
Exemplo n.º 20
0
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)]);
    }
Exemplo n.º 21
0
/*
 * 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;
    }
Exemplo n.º 22
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 *);
	}
Exemplo n.º 23
0
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 {
Exemplo n.º 24
0
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(&params, 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, &params);
}
Exemplo n.º 25
0
/*
 * 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;
		}
	}
}
Exemplo n.º 26
0
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);
        }
    }
}
Exemplo n.º 27
0
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;
}
Exemplo n.º 28
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;
	}
}
Exemplo n.º 29
0
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 {
Exemplo n.º 30
0
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 *);
	}