static int runtest(struct ieee80211vap *vap, struct ciphertest *t) { struct ieee80211_key *key; struct sk_buff *skb = NULL; const struct ieee80211_cipher *cip; u_int8_t mac[IEEE80211_ADDR_LEN]; struct wep_ctx_hw *ctx; int hdrlen; printk("%s: ", t->name); if (!ieee80211_crypto_available(vap, t->cipher)) { printk("FAIL: ieee80211_crypto_available failed\n"); return 0; } /* * Setup key. */ key = &vap->iv_nw_keys[t->keyix]; key->wk_keyix = t->keyix; if (!ieee80211_crypto_newkey(vap, t->cipher, IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key)) { printk("FAIL: ieee80211_crypto_newkey failed\n"); goto bad; } memcpy(key->wk_key, t->key, t->key_len); key->wk_keylen = t->key_len; if (!ieee80211_crypto_setkey(vap, key, mac, NULL)) { printk("FAIL: ieee80211_crypto_setkey failed\n"); goto bad; } cip = key->wk_cipher; /* * Craft encrypted frame from known data. */ skb = ieee80211_dev_alloc_skb(t->encrypted_len); if (skb == NULL) { printk("FAIL: unable to allocate skbuff\n"); goto bad; } memcpy(skb_put(skb, t->encrypted_len), t->encrypted, t->encrypted_len); /* * Decrypt frame. */ hdrlen = ieee80211_hdrspace(vap->iv_ic, skb->data); if (!(*cip->ic_decap)(key, skb, hdrlen)) { printk("FAIL: wep decap failed\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); goto bad; } /* * Verify: frame length, frame contents. */ if (skb->len != t->plaintext_len) { printk("FAIL: decap botch; length mismatch\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); goto bad; } else if (memcmp(skb->data, t->plaintext, t->plaintext_len)) { printk("FAIL: decap botch; data does not compare\n"); cmpfail(skb->data, skb->len, t->plaintext, sizeof(t->plaintext)); goto bad; } /* * Encrypt frame. */ ctx = (struct wep_ctx_hw *) key->wk_private; memcpy(&ctx->wc_iv, t->iv, sizeof(t->iv)); /* for encap/encrypt */ if (!(*cip->ic_encap)(key, skb, t->keyix << 6)) { printk("FAIL: wep encap failed\n"); goto bad; } /* * Verify: frame length, frame contents. */ if (skb->len != t->encrypted_len) { printk("FAIL: encap data length mismatch\n"); cmpfail(skb->data, skb->len, t->encrypted, t->encrypted_len); goto bad; } else if (memcmp(skb->data, t->encrypted, skb->len)) { printk("FAIL: encrypt data does not compare\n"); cmpfail(skb->data, skb->len, t->encrypted, t->encrypted_len); dumpdata("Plaintext", t->plaintext, t->plaintext_len); goto bad; } if (skb != NULL) ieee80211_dev_kfree_skb(&skb); ieee80211_crypto_delkey(vap, key, NULL); printk("PASS\n"); return 1; bad: if (skb != NULL) ieee80211_dev_kfree_skb(&skb); ieee80211_crypto_delkey(vap, key, NULL); return 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; } } }
static int runtest(struct ieee80211vap *vap, struct ciphertest *t) { struct ieee80211_key *key; struct sk_buff *skb = NULL; const struct ieee80211_cipher *cip; u_int8_t mac[IEEE80211_ADDR_LEN]; struct tkip_ctx *ctx; int hdrlen; printk("%s: ", t->name); if (!ieee80211_crypto_available(vap, t->cipher)) { printk("FAIL: ieee80211_crypto_available failed\n"); return 0; } /* * Setup key. */ key = &vap->iv_nw_keys[t->keyix]; key->wk_keyix = t->keyix; if (!ieee80211_crypto_newkey(vap, t->cipher, IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key)) { printk("FAIL: ieee80211_crypto_newkey failed\n"); goto bad; } memcpy(key->wk_key, t->key, t->key_len); key->wk_keylen = 128 / NBBY; memset(key->wk_keyrsc, 0, sizeof(key->wk_keyrsc)); key->wk_keytsc = 0; if (!ieee80211_crypto_setkey(vap, key, mac, NULL)) { printk("FAIL: ieee80211_crypto_setkey failed\n"); goto bad; } /* * Craft frame from plaintext data. Note that * we leave the MIC off as we'll add it ourself * and then check it against the reference data. */ cip = key->wk_cipher; skb = ieee80211_dev_alloc_skb(t->plaintext_len + cip->ic_miclen + cip->ic_header + cip->ic_trailer); if (skb == NULL) { printk("FAIL: unable to allocate skbuff\n"); goto bad; } skb_reserve(skb, cip->ic_header); memcpy(skb_put(skb, t->plaintext_len - cip->ic_miclen), t->plaintext, t->plaintext_len - cip->ic_miclen); /* * Add MIC. */ if (!ieee80211_crypto_enmic(vap, key, skb, 0)) { printk("FAIL: tkip enmic failed\n"); goto bad; } /* * Verify: frame length, frame contents. */ if (skb->len != t->plaintext_len) { printk("FAIL: enmic botch; length mismatch\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); goto bad; } if (memcmp(skb->data, t->plaintext, t->plaintext_len)) { printk("FAIL: enmic botch\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); goto bad; } /* * Encrypt frame w/ MIC. */ if (!(*cip->ic_encap)(key, skb, t->keyix << 6)) { printk("FAIL: tkip encap failed\n"); goto bad; } /* * Verify: phase1, phase2, frame length, frame contents. */ ctx = key->wk_private; if (memcmp(ctx->tx_ttak, t->phase1, t->phase1_len)) { printk("FAIL: encrypt phase1 botch\n"); cmpfail(ctx->tx_ttak, sizeof(ctx->tx_ttak), t->phase1, t->phase1_len); goto bad; } else if (memcmp(ctx->tx_rc4key, t->phase2, t->phase2_len)) { printf("FAIL: encrypt phase2 botch\n"); cmpfail(ctx->tx_rc4key, sizeof(ctx->tx_rc4key), t->phase2, t->phase2_len); goto bad; } else if (skb->len != t->encrypted_len) { printk("FAIL: encrypt data length mismatch\n"); cmpfail(skb->data, skb->len, t->encrypted, t->encrypted_len); goto bad; } else if (memcmp(skb->data, t->encrypted, skb->len)) { printk("FAIL: encrypt data does not compare\n"); cmpfail(skb->data, skb->len, t->encrypted, t->encrypted_len); dumpdata("Plaintext", t->plaintext, t->plaintext_len); goto bad; } /* * Decrypt frame. */ hdrlen = ieee80211_hdrspace(vap->iv_ic, skb->data); if (!(*cip->ic_decap)(key, skb, hdrlen)) { printk("FAIL: tkip decap failed\n"); /* * Check reason for failure: phase1, phase2, frame data (ICV). */ if (memcmp(ctx->rx_ttak, t->phase1, t->phase1_len)) { printk("decrypt phase1 botch\n"); cmpfail(ctx->rx_ttak, sizeof(ctx->rx_ttak), t->phase1, t->phase1_len); } else if (memcmp(ctx->rx_rc4key, t->phase2, t->phase2_len)) { printf("decrypt phase2 botch\n"); cmpfail(ctx->rx_rc4key, sizeof(ctx->rx_rc4key), t->phase2, t->phase2_len); } else { printk("decrypt data does not compare\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); } goto bad; } /* * Verify: frame length, frame contents. */ if (skb->len != t->plaintext_len) { printk("FAIL: decap botch; length mismatch\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); goto bad; } if (memcmp(skb->data, t->plaintext, t->plaintext_len)) { printk("FAIL: decap botch; data does not compare\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); goto bad; } /* * De-MIC decrypted frame. */ if (!ieee80211_crypto_demic(vap, key, skb, hdrlen, 0)) { printk("FAIL: tkip demic failed\n"); goto bad; } /* XXX check frame length and contents... */ ieee80211_dev_kfree_skb(&skb); ieee80211_crypto_delkey(vap, key, NULL); printk("PASS\n"); return 1; bad: if (skb != NULL) ieee80211_dev_kfree_skb(&skb); ieee80211_crypto_delkey(vap, key, NULL); return 0; }
static int runtest(struct ieee80211vap *vap, struct ciphertest *t) { struct ieee80211_key *key; struct sk_buff *skb = NULL; const struct ieee80211_cipher *cip; u_int8_t mac[IEEE80211_ADDR_LEN]; int hdrlen; printk("%s: ", t->name); if (!ieee80211_crypto_available(vap, t->cipher)) { printk("FAIL: ieee80211_crypto_available failed\n"); return 0; } /* * Setup key. */ key = &vap->iv_nw_keys[t->keyix]; key->wk_keyix = t->keyix; if (!ieee80211_crypto_newkey(vap, t->cipher, IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key)) { printk("FAIL: ieee80211_crypto_newkey failed\n"); goto bad; } memcpy(key->wk_key, t->key, t->key_len); key->wk_keylen = t->key_len; memset(key->wk_keyrsc, 0, sizeof(key->wk_keyrsc)); key->wk_keytsc = t->pn - 1; /* PN-1 since we do encap */ if (!ieee80211_crypto_setkey(vap, key, mac, NULL)) { printk("FAIL: ieee80211_crypto_setkey failed\n"); goto bad; } /* * Craft frame from plaintext data. */ cip = key->wk_cipher; skb = ieee80211_dev_alloc_skb(t->plaintext_len + cip->ic_header + cip->ic_trailer); if (skb == NULL) { printk("FAIL: unable to allocate skbuff\n"); goto bad; } skb_reserve(skb, cip->ic_header); memcpy(skb_put(skb, t->plaintext_len), t->plaintext, t->plaintext_len); /* * Encrypt frame w/ MIC. */ if (!(*cip->ic_encap)(key, skb, t->keyix << 6)) { printk("FAIL: ccmp encap failed\n"); goto bad; } /* * Verify: frame length, frame contents. */ if (skb->len != t->encrypted_len) { printk("FAIL: encap data length mismatch\n"); cmpfail(skb->data, skb->len, t->encrypted, t->encrypted_len); goto bad; } else if (memcmp(skb->data, t->encrypted, skb->len)) { printk("FAIL: encrypt data does not compare\n"); cmpfail(skb->data, skb->len, t->encrypted, t->encrypted_len); dumpdata("Plaintext", t->plaintext, t->plaintext_len); goto bad; } /* * Decrypt frame; strip MIC. */ hdrlen = ieee80211_hdrspace(vap->iv_ic, skb->data); if (!(*cip->ic_decap)(key, skb, hdrlen)) { printk("FAIL: ccmp decap failed\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); goto bad; } /* * Verify: frame length, frame contents. */ if (skb->len != t->plaintext_len) { printk("FAIL: decap botch; length mismatch\n"); cmpfail(skb->data, skb->len, t->plaintext, t->plaintext_len); goto bad; } else if (memcmp(skb->data, t->plaintext, t->plaintext_len)) { printk("FAIL: decap botch; data does not compare\n"); cmpfail(skb->data, skb->len, t->plaintext, sizeof(t->plaintext)); goto bad; } ieee80211_dev_kfree_skb(&skb); ieee80211_crypto_delkey(vap, key, NULL); printk("PASS\n"); return 1; bad: if (skb != NULL) ieee80211_dev_kfree_skb(&skb); ieee80211_crypto_delkey(vap, key, NULL); return 0; }