提交 68762f3d 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [TG3]: Add TG3_FLAG_SUPPORT_MSI flag.
  [TG3]: Eliminate the TG3_FLAG_5701_REG_WRITE_BUG flag.
  [TG3]: Eliminate the TG3_FLAG_GOT_SERDES_FLOWCTL flag.
  [TG3]: Remove reset during MAC address changes.
  [TG3]: WoL fixes.
  [TG3]: Clear GPIO mask before storing.
  [TG3]: Improve NVRAM sizing.
  [TG3]: Fix TSO bugs.
  [MAC80211]: Add maintainers entry for mac80211.
  [MAC80211]: Add debugfs attributes.
  [MAC80211]: Add mac80211 wireless stack.
  [MAC80211]: Add generic include/linux/ieee80211.h
  [NETLINK]: Remove references to process ID
  [AF_IUCV]: Compile fix - adopt to skbuff changes.
......@@ -2228,6 +2228,16 @@ M: philb@gnu.org
W: http://www.tazenda.demon.co.uk/phil/linux-hp
S: Maintained
MAC80211
P: Jiri Benc
M: jbenc@suse.cz
P: Michael Wu
M: flamingice@sourmilk.net
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/
T: git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git
S: Maintained
MARVELL YUKON / SYSKONNECT DRIVER
P: Mirko Lindner
M: mlindner@syskonnect.de
......
......@@ -1300,9 +1300,11 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
msleep(1);
}
}
tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
WOL_DRV_STATE_SHUTDOWN |
WOL_DRV_WOL | WOL_SET_MAGIC_PKT);
if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
WOL_DRV_STATE_SHUTDOWN |
WOL_DRV_WOL |
WOL_SET_MAGIC_PKT);
pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
......@@ -2593,10 +2595,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
{
int current_link_up = 0;
if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
if (!(mac_status & MAC_STATUS_PCS_SYNCED))
goto out;
}
if (tp->link_config.autoneg == AUTONEG_ENABLE) {
u32 flags;
......@@ -2614,7 +2614,6 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
tg3_setup_flow_control(tp, local_adv, remote_adv);
tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
current_link_up = 1;
}
for (i = 0; i < 30; i++) {
......@@ -2637,7 +2636,6 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
} else {
/* Forcing 1000FD link up. */
current_link_up = 1;
tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
udelay(40);
......@@ -3895,8 +3893,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
entry = tp->tx_prod;
base_flags = 0;
mss = 0;
if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
(mss = skb_shinfo(skb)->gso_size) != 0) {
if ((mss = skb_shinfo(skb)->gso_size) != 0) {
int tcp_opt_len, ip_tcp_len;
if (skb_header_cloned(skb) &&
......@@ -4053,8 +4050,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
if (skb->ip_summed == CHECKSUM_PARTIAL)
base_flags |= TXD_FLAG_TCPUDP_CSUM;
mss = 0;
if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
(mss = skb_shinfo(skb)->gso_size) != 0) {
if ((mss = skb_shinfo(skb)->gso_size) != 0) {
struct iphdr *iph;
int tcp_opt_len, ip_tcp_len, hdr_len;
......@@ -5934,7 +5930,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
/* tp->lock is held. */
static void __tg3_set_mac_addr(struct tg3 *tp)
static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
{
u32 addr_high, addr_low;
int i;
......@@ -5946,6 +5942,8 @@ static void __tg3_set_mac_addr(struct tg3 *tp)
(tp->dev->dev_addr[4] << 8) |
(tp->dev->dev_addr[5] << 0));
for (i = 0; i < 4; i++) {
if (i == 1 && skip_mac_1)
continue;
tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
}
......@@ -5972,7 +5970,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
{
struct tg3 *tp = netdev_priv(dev);
struct sockaddr *addr = p;
int err = 0;
int err = 0, skip_mac_1 = 0;
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
......@@ -5983,22 +5981,21 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
return 0;
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
/* Reset chip so that ASF can re-init any MAC addresses it
* needs.
*/
tg3_netif_stop(tp);
tg3_full_lock(tp, 1);
u32 addr0_high, addr0_low, addr1_high, addr1_low;
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
err = tg3_restart_hw(tp, 0);
if (!err)
tg3_netif_start(tp);
tg3_full_unlock(tp);
} else {
spin_lock_bh(&tp->lock);
__tg3_set_mac_addr(tp);
spin_unlock_bh(&tp->lock);
addr0_high = tr32(MAC_ADDR_0_HIGH);
addr0_low = tr32(MAC_ADDR_0_LOW);
addr1_high = tr32(MAC_ADDR_1_HIGH);
addr1_low = tr32(MAC_ADDR_1_LOW);
/* Skip MAC addr 1 if ASF is using it. */
if ((addr0_high != addr1_high || addr0_low != addr1_low) &&
!(addr1_high == 0 && addr1_low == 0))
skip_mac_1 = 1;
}
spin_lock_bh(&tp->lock);
__tg3_set_mac_addr(tp, skip_mac_1);
spin_unlock_bh(&tp->lock);
return err;
}
......@@ -6315,7 +6312,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tp->rx_jumbo_ptr);
/* Initialize MAC address and backoff seed. */
__tg3_set_mac_addr(tp);
__tg3_set_mac_addr(tp, 0);
/* MTU + ethernet header + FCS + optional VLAN tag */
tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8);
......@@ -6346,8 +6343,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
(tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
!(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
......@@ -6457,6 +6453,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
tp->grc_local_ctrl &= ~gpio_mask;
tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
/* GPIO1 must be driven high for eeprom write protect */
......@@ -7036,11 +7033,7 @@ static int tg3_open(struct net_device *dev)
if (err)
return err;
if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
(GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
(GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) &&
!((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) &&
(tp->pdev_peer == tp->pdev))) {
if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) {
/* All MSI supporting chips should support tagged
* status. Assert that this is the case.
*/
......@@ -7399,9 +7392,7 @@ static int tg3_close(struct net_device *dev)
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
tp->tg3_flags &=
~(TG3_FLAG_INIT_COMPLETE |
TG3_FLAG_GOT_SERDES_FLOWCTL);
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
tg3_full_unlock(tp);
......@@ -8036,7 +8027,10 @@ static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct tg3 *tp = netdev_priv(dev);
wol->supported = WAKE_MAGIC;
if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
wol->supported = WAKE_MAGIC;
else
wol->supported = 0;
wol->wolopts = 0;
if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
wol->wolopts = WAKE_MAGIC;
......@@ -8050,8 +8044,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if (wol->wolopts & ~WAKE_MAGIC)
return -EINVAL;
if ((wol->wolopts & WAKE_MAGIC) &&
tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
!(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
!(tp->tg3_flags & TG3_FLAG_WOL_CAP))
return -EINVAL;
spin_lock_bh(&tp->lock);
......@@ -9289,7 +9282,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
return;
}
}
tp->nvram_size = 0x20000;
tp->nvram_size = 0x80000;
}
static void __devinit tg3_get_nvram_info(struct tg3 *tp)
......@@ -9408,33 +9401,31 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
{
u32 nvcfg1;
u32 nvcfg1, protect = 0;
nvcfg1 = tr32(NVRAM_CFG1);
/* NVRAM protection for TPM */
if (nvcfg1 & (1 << 27))
if (nvcfg1 & (1 << 27)) {
tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
protect = 1;
}
switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ:
case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ:
tp->nvram_jedecnum = JEDEC_ATMEL;
tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
tw32(NVRAM_CFG1, nvcfg1);
break;
case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
switch (nvcfg1) {
case FLASH_5755VENDOR_ATMEL_FLASH_1:
case FLASH_5755VENDOR_ATMEL_FLASH_2:
case FLASH_5755VENDOR_ATMEL_FLASH_3:
case FLASH_5755VENDOR_ATMEL_FLASH_4:
tp->nvram_jedecnum = JEDEC_ATMEL;
tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
tp->tg3_flags2 |= TG3_FLG2_FLASH;
tp->nvram_pagesize = 264;
if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1)
tp->nvram_size = (protect ? 0x3e200 : 0x80000);
else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
tp->nvram_size = (protect ? 0x1f200 : 0x40000);
else
tp->nvram_size = (protect ? 0x1f200 : 0x20000);
break;
case FLASH_5752VENDOR_ST_M45PE10:
case FLASH_5752VENDOR_ST_M45PE20:
......@@ -9443,6 +9434,12 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
tp->tg3_flags2 |= TG3_FLG2_FLASH;
tp->nvram_pagesize = 256;
if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10)
tp->nvram_size = (protect ? 0x10000 : 0x20000);
else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20)
tp->nvram_size = (protect ? 0x10000 : 0x40000);
else
tp->nvram_size = (protect ? 0x20000 : 0x80000);
break;
}
}
......@@ -9518,6 +9515,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
}
tg3_enable_nvram_access(tp);
tp->nvram_size = 0;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
tg3_get_5752_nvram_info(tp);
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
......@@ -9529,7 +9528,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
else
tg3_get_nvram_info(tp);
tg3_get_nvram_size(tp);
if (tp->nvram_size == 0)
tg3_get_nvram_size(tp);
tg3_disable_nvram_access(tp);
tg3_nvram_unlock(tp);
......@@ -9996,8 +9996,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->phy_id = PHY_ID_INVALID;
tp->led_ctrl = LED_CTRL_MODE_PHY_1;
/* Assume an onboard device by default. */
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
/* Assume an onboard device and WOL capable by default. */
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT | TG3_FLAG_WOL_CAP;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) {
......@@ -10120,8 +10120,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
}
if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
!(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
if (cfg2 & (1 << 17))
tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
......@@ -10399,6 +10400,8 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
}
}
static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
static int __devinit tg3_get_invariants(struct tg3 *tp)
{
static struct pci_device_id write_reorder_chipsets[] = {
......@@ -10554,6 +10557,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->pci_hdr_type = (cacheline_sz_reg >> 16) & 0xff;
tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff;
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
tp->pdev_peer = tg3_find_peer(tp);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
......@@ -10567,6 +10574,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI;
if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX ||
GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 &&
tp->pci_chip_rev_id <= CHIPREV_ID_5714_A2 &&
tp->pdev_peer == tp->pdev))
tp->tg3_flags &= ~TG3_FLAG_SUPPORT_MSI;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
......@@ -10668,17 +10683,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
/* Back to back register writes can cause problems on this chip,
* the workaround is to read back all reg writes except those to
* mailbox regs. See tg3_write_indirect_reg32().
*
* PCI Express 5750_A0 rev chips need this workaround too.
*/
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
tp->pci_chip_rev_id == CHIPREV_ID_5750_A0))
tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG;
if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
......@@ -10702,8 +10706,19 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
/* Various workaround register access methods */
if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG)
tp->write32 = tg3_write_indirect_reg32;
else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG)
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) {
/*
* Back to back register writes can cause problems on these
* chips, the workaround is to read back all reg writes
* except those to mailbox regs.
*
* See tg3_write_indirect_reg32().
*/
tp->write32 = tg3_write_flush_reg32;
}
if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
......@@ -11892,10 +11907,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tp->rx_pending = 63;
}
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
tp->pdev_peer = tg3_find_peer(tp);
err = tg3_get_device_address(tp);
if (err) {
printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
......
......@@ -131,6 +131,7 @@
#define CHIPREV_ID_5752_A0_HW 0x5000
#define CHIPREV_ID_5752_A0 0x6000
#define CHIPREV_ID_5752_A1 0x6001
#define CHIPREV_ID_5714_A2 0x9002
#define CHIPREV_ID_5906_A1 0xc001
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07
......@@ -2199,7 +2200,6 @@ struct tg3 {
#define TG3_FLAG_USE_LINKCHG_REG 0x00000008
#define TG3_FLAG_USE_MI_INTERRUPT 0x00000010
#define TG3_FLAG_ENABLE_ASF 0x00000020
#define TG3_FLAG_5701_REG_WRITE_BUG 0x00000040
#define TG3_FLAG_POLL_SERDES 0x00000080
#define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100
#define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200
......@@ -2215,14 +2215,14 @@ struct tg3 {
#define TG3_FLAG_PCI_32BIT 0x00080000
#define TG3_FLAG_SRAM_USE_CONFIG 0x00100000
#define TG3_FLAG_TX_RECOVERY_PENDING 0x00200000
#define TG3_FLAG_SERDES_WOL_CAP 0x00400000
#define TG3_FLAG_WOL_CAP 0x00400000
#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000
#define TG3_FLAG_10_100_ONLY 0x01000000
#define TG3_FLAG_PAUSE_AUTONEG 0x02000000
#define TG3_FLAG_IN_RESET_TASK 0x04000000
#define TG3_FLAG_40BIT_DMA_BUG 0x08000000
#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000
#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
#define TG3_FLAG_SUPPORT_MSI 0x20000000
#define TG3_FLAG_CHIP_RESETTING 0x40000000
#define TG3_FLAG_INIT_COMPLETE 0x80000000
u32 tg3_flags2;
......
/*
* IEEE 802.11 defines
*
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
* <jkmaline@cc.hut.fi>
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
* Copyright (c) 2005, Devicescape Software, Inc.
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef IEEE80211_H
#define IEEE80211_H
#include <linux/types.h>
#define FCS_LEN 4
#define IEEE80211_FCTL_VERS 0x0003
#define IEEE80211_FCTL_FTYPE 0x000c
#define IEEE80211_FCTL_STYPE 0x00f0
#define IEEE80211_FCTL_TODS 0x0100
#define IEEE80211_FCTL_FROMDS 0x0200
#define IEEE80211_FCTL_MOREFRAGS 0x0400
#define IEEE80211_FCTL_RETRY 0x0800
#define IEEE80211_FCTL_PM 0x1000
#define IEEE80211_FCTL_MOREDATA 0x2000
#define IEEE80211_FCTL_PROTECTED 0x4000
#define IEEE80211_FCTL_ORDER 0x8000
#define IEEE80211_SCTL_FRAG 0x000F
#define IEEE80211_SCTL_SEQ 0xFFF0
#define IEEE80211_FTYPE_MGMT 0x0000
#define IEEE80211_FTYPE_CTL 0x0004
#define IEEE80211_FTYPE_DATA 0x0008
/* management */
#define IEEE80211_STYPE_ASSOC_REQ 0x0000
#define IEEE80211_STYPE_ASSOC_RESP 0x0010
#define IEEE80211_STYPE_REASSOC_REQ 0x0020
#define IEEE80211_STYPE_REASSOC_RESP 0x0030
#define IEEE80211_STYPE_PROBE_REQ 0x0040
#define IEEE80211_STYPE_PROBE_RESP 0x0050
#define IEEE80211_STYPE_BEACON 0x0080
#define IEEE80211_STYPE_ATIM 0x0090
#define IEEE80211_STYPE_DISASSOC 0x00A0
#define IEEE80211_STYPE_AUTH 0x00B0
#define IEEE80211_STYPE_DEAUTH 0x00C0
#define IEEE80211_STYPE_ACTION 0x00D0
/* control */
#define IEEE80211_STYPE_PSPOLL 0x00A0
#define IEEE80211_STYPE_RTS 0x00B0
#define IEEE80211_STYPE_CTS 0x00C0
#define IEEE80211_STYPE_ACK 0x00D0
#define IEEE80211_STYPE_CFEND 0x00E0
#define IEEE80211_STYPE_CFENDACK 0x00F0
/* data */
#define IEEE80211_STYPE_DATA 0x0000
#define IEEE80211_STYPE_DATA_CFACK 0x0010
#define IEEE80211_STYPE_DATA_CFPOLL 0x0020
#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030
#define IEEE80211_STYPE_NULLFUNC 0x0040
#define IEEE80211_STYPE_CFACK 0x0050
#define IEEE80211_STYPE_CFPOLL 0x0060
#define IEEE80211_STYPE_CFACKPOLL 0x0070
#define IEEE80211_STYPE_QOS_DATA 0x0080
#define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090
#define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0
#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0
#define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0
#define IEEE80211_STYPE_QOS_CFACK 0x00D0
#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0
#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0
/* miscellaneous IEEE 802.11 constants */
#define IEEE80211_MAX_FRAG_THRESHOLD 2346
#define IEEE80211_MAX_RTS_THRESHOLD 2347
#define IEEE80211_MAX_AID 2007
#define IEEE80211_MAX_TIM_LEN 251
#define IEEE80211_MAX_DATA_LEN 2304
/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
6.2.1.1.2.
The figure in section 7.1.2 suggests a body size of up to 2312
bytes is allowed, which is a bit confusing, I suspect this
represents the 2304 bytes of real data, plus a possible 8 bytes of
WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
#define IEEE80211_MAX_SSID_LEN 32
struct ieee80211_hdr {
__le16 frame_control;
__le16 duration_id;
u8 addr1[6];
u8 addr2[6];
u8 addr3[6];
__le16 seq_ctrl;
u8 addr4[6];
} __attribute__ ((packed));
struct ieee80211_mgmt {
__le16 frame_control;
__le16 duration;
u8 da[6];
u8 sa[6];
u8 bssid[6];
__le16 seq_ctrl;
union {
struct {
__le16 auth_alg;
__le16 auth_transaction;
__le16 status_code;
/* possibly followed by Challenge text */
u8 variable[0];
} __attribute__ ((packed)) auth;
struct {
__le16 reason_code;
} __attribute__ ((packed)) deauth;
struct {
__le16 capab_info;
__le16 listen_interval;
/* followed by SSID and Supported rates */
u8 variable[0];
} __attribute__ ((packed)) assoc_req;
struct {
__le16 capab_info;
__le16 status_code;
__le16 aid;
/* followed by Supported rates */
u8 variable[0];
} __attribute__ ((packed)) assoc_resp, reassoc_resp;
struct {
__le16 capab_info;
__le16 listen_interval;
u8 current_ap[6];
/* followed by SSID and Supported rates */
u8 variable[0];
} __attribute__ ((packed)) reassoc_req;
struct {
__le16 reason_code;
} __attribute__ ((packed)) disassoc;
struct {
__le64 timestamp;
__le16 beacon_int;
__le16 capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params, TIM */
u8 variable[0];
} __attribute__ ((packed)) beacon;
struct {
/* only variable items: SSID, Supported rates */
u8 variable[0];
} __attribute__ ((packed)) probe_req;
struct {
__le64 timestamp;
__le16 beacon_int;
__le16 capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params */
u8 variable[0];
} __attribute__ ((packed)) probe_resp;
struct {
u8 category;
union {
struct {
u8 action_code;
u8 dialog_token;
u8 status_code;
u8 variable[0];
} __attribute__ ((packed)) wme_action;
struct{
u8 action_code;
u8 element_id;
u8 length;
u8 switch_mode;
u8 new_chan;
u8 switch_count;
} __attribute__((packed)) chan_switch;
} u;
} __attribute__ ((packed)) action;
} u;
} __attribute__ ((packed));
/* Control frames */
struct ieee80211_rts {
__le16 frame_control;
__le16 duration;
u8 ra[6];
u8 ta[6];
} __attribute__ ((packed));
struct ieee80211_cts {
__le16 frame_control;
__le16 duration;
u8 ra[6];
} __attribute__ ((packed));
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
#define WLAN_AUTH_FAST_BSS_TRANSITION 2
#define WLAN_AUTH_LEAP 128
#define WLAN_AUTH_CHALLENGE_LEN 128
#define WLAN_CAPABILITY_ESS (1<<0)
#define WLAN_CAPABILITY_IBSS (1<<1)
#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
#define WLAN_CAPABILITY_PRIVACY (1<<4)
#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
#define WLAN_CAPABILITY_PBCC (1<<6)
#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
/* 802.11h */
#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
#define WLAN_CAPABILITY_QOS (1<<9)
#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
/* Status codes */
enum ieee80211_statuscode {
WLAN_STATUS_SUCCESS = 0,
WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
WLAN_STATUS_CAPS_UNSUPPORTED = 10,
WLAN_STATUS_REASSOC_NO_ASSOC = 11,
WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
WLAN_STATUS_CHALLENGE_FAIL = 15,
WLAN_STATUS_AUTH_TIMEOUT = 16,
WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
WLAN_STATUS_ASSOC_DENIED_RATES = 18,
/* 802.11b */
WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
/* 802.11h */
WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
/* 802.11g */
WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
/* 802.11i */
WLAN_STATUS_INVALID_IE = 40,
WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
WLAN_STATUS_INVALID_AKMP = 43,
WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
};
/* Reason codes */
enum ieee80211_reasoncode {
WLAN_REASON_UNSPECIFIED = 1,
WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
WLAN_REASON_DEAUTH_LEAVING = 3,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
WLAN_REASON_DISASSOC_AP_BUSY = 5,
WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
/* 802.11h */
WLAN_REASON_DISASSOC_BAD_POWER = 10,
WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
/* 802.11i */
WLAN_REASON_INVALID_IE = 13,
WLAN_REASON_MIC_FAILURE = 14,
WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
WLAN_REASON_IE_DIFFERENT = 17,
WLAN_REASON_INVALID_GROUP_CIPHER = 18,
WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
WLAN_REASON_INVALID_AKMP = 20,
WLAN_REASON_UNSUPP_RSN_VERSION = 21,
WLAN_REASON_INVALID_RSN_IE_CAP = 22,
WLAN_REASON_IEEE8021X_FAILED = 23,
WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
};
/* Information Element IDs */
enum ieee80211_eid {
WLAN_EID_SSID = 0,
WLAN_EID_SUPP_RATES = 1,
WLAN_EID_FH_PARAMS = 2,
WLAN_EID_DS_PARAMS = 3,
WLAN_EID_CF_PARAMS = 4,
WLAN_EID_TIM = 5,
WLAN_EID_IBSS_PARAMS = 6,
WLAN_EID_CHALLENGE = 16,
/* 802.11d */
WLAN_EID_COUNTRY = 7,
WLAN_EID_HP_PARAMS = 8,
WLAN_EID_HP_TABLE = 9,
WLAN_EID_REQUEST = 10,
/* 802.11h */
WLAN_EID_PWR_CONSTRAINT = 32,
WLAN_EID_PWR_CAPABILITY = 33,
WLAN_EID_TPC_REQUEST = 34,
WLAN_EID_TPC_REPORT = 35,
WLAN_EID_SUPPORTED_CHANNELS = 36,
WLAN_EID_CHANNEL_SWITCH = 37,
WLAN_EID_MEASURE_REQUEST = 38,
WLAN_EID_MEASURE_REPORT = 39,
WLAN_EID_QUIET = 40,
WLAN_EID_IBSS_DFS = 41,
/* 802.11g */
WLAN_EID_ERP_INFO = 42,
WLAN_EID_EXT_SUPP_RATES = 50,
/* 802.11i */
WLAN_EID_RSN = 48,
WLAN_EID_WPA = 221,
WLAN_EID_GENERIC = 221,
WLAN_EID_VENDOR_SPECIFIC = 221,
WLAN_EID_QOS_PARAMETER = 222
};
/* cipher suite selectors */
#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00
#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
/* reserved: 0x000FAC03 */
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
#define WLAN_MAX_KEY_LEN 32
#endif /* IEEE80211_H */
......@@ -31,7 +31,7 @@ struct sockaddr_nl
{
sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* zero */
__u32 nl_pid; /* process pid */
__u32 nl_pid; /* port ID */
__u32 nl_groups; /* multicast groups mask */
};
......@@ -41,7 +41,7 @@ struct nlmsghdr
__u16 nlmsg_type; /* Message content */
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process PID */
__u32 nlmsg_pid; /* Sending process port ID */
};
/* Flags values */
......
此差异已折叠。
......@@ -220,6 +220,7 @@ config FIB_RULES
menu "Wireless"
source "net/wireless/Kconfig"
source "net/mac80211/Kconfig"
source "net/ieee80211/Kconfig"
endmenu
......
......@@ -45,6 +45,8 @@ obj-$(CONFIG_ECONET) += econet/
obj-$(CONFIG_VLAN_8021Q) += 8021q/
obj-$(CONFIG_IP_DCCP) += dccp/
obj-$(CONFIG_IP_SCTP) += sctp/
obj-y += wireless/
obj-$(CONFIG_MAC80211) += mac80211/
obj-$(CONFIG_IEEE80211) += ieee80211/
obj-$(CONFIG_TIPC) += tipc/
obj-$(CONFIG_NETLABEL) += netlabel/
......@@ -53,5 +55,3 @@ obj-$(CONFIG_IUCV) += iucv/
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
endif
obj-y += wireless/
......@@ -961,7 +961,7 @@ static void iucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
}
static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len,
struct sk_buff_head fragmented_skb_q)
struct sk_buff_head *fragmented_skb_q)
{
int dataleft, size, copied = 0;
struct sk_buff *nskb;
......@@ -981,8 +981,8 @@ static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len,
copied += size;
dataleft -= size;
nskb->h.raw = nskb->data;
nskb->nh.raw = nskb->data;
skb_reset_transport_header(nskb);
skb_reset_network_header(nskb);
nskb->len = size;
skb_queue_tail(fragmented_skb_q, nskb);
......
config MAC80211
tristate "Generic IEEE 802.11 Networking Stack (mac80211)"
depends on EXPERIMENTAL
select CRYPTO
select CRYPTO_ECB
select CRYPTO_ARC4
select CRYPTO_AES
select CRC32
select WIRELESS_EXT
select CFG80211
select NET_SCH_FIFO
---help---
This option enables the hardware independent IEEE 802.11
networking stack.
config MAC80211_LEDS
bool "Enable LED triggers"
depends on MAC80211 && LEDS_TRIGGERS
---help---
This option enables a few LED triggers for different
packet receive/transmit events.
config MAC80211_DEBUGFS
bool "Export mac80211 internals in DebugFS"
depends on MAC80211 && DEBUG_FS
---help---
Select this to see extensive information about
the internal state of mac80211 in debugfs.
Say N unless you know you need this.
config MAC80211_DEBUG
bool "Enable debugging output"
depends on MAC80211
---help---
This option will enable debug tracing output for the
ieee80211 network stack.
If you are not trying to debug or develop the ieee80211
subsystem, you most likely want to say N here.
config MAC80211_VERBOSE_DEBUG
bool "Verbose debugging output"
depends on MAC80211_DEBUG
config MAC80211_LOWTX_FRAME_DUMP
bool "Debug frame dumping"
depends on MAC80211_DEBUG
---help---
Selecting this option will cause the stack to
print a message for each frame that is handed
to the lowlevel driver for transmission. This
message includes all MAC addresses and the
frame control field.
If unsure, say N and insert the debugging code
you require into the driver you are debugging.
config TKIP_DEBUG
bool "TKIP debugging"
depends on MAC80211_DEBUG
config MAC80211_DEBUG_COUNTERS
bool "Extra statistics for TX/RX debugging"
depends on MAC80211_DEBUG
config MAC80211_IBSS_DEBUG
bool "Support for IBSS testing"
depends on MAC80211_DEBUG
---help---
Say Y here if you intend to debug the IBSS code.
config MAC80211_VERBOSE_PS_DEBUG
bool "Verbose powersave mode debugging"
depends on MAC80211_DEBUG
---help---
Say Y here to print out verbose powersave
mode debug messages.
obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o
mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o
mac80211-objs := \
ieee80211.o \
ieee80211_ioctl.o \
sta_info.o \
wep.o \
wpa.o \
ieee80211_sta.o \
ieee80211_iface.o \
ieee80211_rate.o \
michael.o \
tkip.o \
aes_ccm.o \
wme.o \
ieee80211_cfg.o \
$(mac80211-objs-y)
/*
* Copyright 2003-2004, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
#include <asm/scatterlist.h>
#include <net/mac80211.h>
#include "ieee80211_key.h"
#include "aes_ccm.h"
static void ieee80211_aes_encrypt(struct crypto_cipher *tfm,
const u8 pt[16], u8 ct[16])
{
crypto_cipher_encrypt_one(tfm, ct, pt);
}
static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
u8 *b, u8 *s_0, u8 *a)
{
int i;
ieee80211_aes_encrypt(tfm, b_0, b);
/* Extra Authenticate-only data (always two AES blocks) */
for (i = 0; i < AES_BLOCK_LEN; i++)
aad[i] ^= b[i];
ieee80211_aes_encrypt(tfm, aad, b);
aad += AES_BLOCK_LEN;
for (i = 0; i < AES_BLOCK_LEN; i++)
aad[i] ^= b[i];
ieee80211_aes_encrypt(tfm, aad, a);
/* Mask out bits from auth-only-b_0 */
b_0[0] &= 0x07;
/* S_0 is used to encrypt T (= MIC) */
b_0[14] = 0;
b_0[15] = 0;
ieee80211_aes_encrypt(tfm, b_0, s_0);
}
void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
u8 *b_0, u8 *aad, u8 *data, size_t data_len,
u8 *cdata, u8 *mic)
{
int i, j, last_len, num_blocks;
u8 *pos, *cpos, *b, *s_0, *e;
b = scratch;
s_0 = scratch + AES_BLOCK_LEN;
e = scratch + 2 * AES_BLOCK_LEN;
num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
last_len = data_len % AES_BLOCK_LEN;
aes_ccm_prepare(tfm, b_0, aad, b, s_0, b);
/* Process payload blocks */
pos = data;
cpos = cdata;
for (j = 1; j <= num_blocks; j++) {
int blen = (j == num_blocks && last_len) ?
last_len : AES_BLOCK_LEN;
/* Authentication followed by encryption */
for (i = 0; i < blen; i++)
b[i] ^= pos[i];
ieee80211_aes_encrypt(tfm, b, b);
b_0[14] = (j >> 8) & 0xff;
b_0[15] = j & 0xff;
ieee80211_aes_encrypt(tfm, b_0, e);
for (i = 0; i < blen; i++)
*cpos++ = *pos++ ^ e[i];
}
for (i = 0; i < CCMP_MIC_LEN; i++)
mic[i] = b[i] ^ s_0[i];
}
int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
u8 *mic, u8 *data)
{
int i, j, last_len, num_blocks;
u8 *pos, *cpos, *b, *s_0, *a;
b = scratch;
s_0 = scratch + AES_BLOCK_LEN;
a = scratch + 2 * AES_BLOCK_LEN;
num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
last_len = data_len % AES_BLOCK_LEN;
aes_ccm_prepare(tfm, b_0, aad, b, s_0, a);
/* Process payload blocks */
cpos = cdata;
pos = data;
for (j = 1; j <= num_blocks; j++) {
int blen = (j == num_blocks && last_len) ?
last_len : AES_BLOCK_LEN;
/* Decryption followed by authentication */
b_0[14] = (j >> 8) & 0xff;
b_0[15] = j & 0xff;
ieee80211_aes_encrypt(tfm, b_0, b);
for (i = 0; i < blen; i++) {
*pos = *cpos++ ^ b[i];
a[i] ^= *pos++;
}
ieee80211_aes_encrypt(tfm, a, a);
}
for (i = 0; i < CCMP_MIC_LEN; i++) {
if ((mic[i] ^ s_0[i]) != a[i])
return -1;
}
return 0;
}
struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[])
{
struct crypto_cipher *tfm;
tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm))
return NULL;
crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
return tfm;
}
void ieee80211_aes_key_free(struct crypto_cipher *tfm)
{
if (tfm)
crypto_free_cipher(tfm);
}
/*
* Copyright 2003-2004, Instant802 Networks, Inc.
* Copyright 2006, Devicescape Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef AES_CCM_H
#define AES_CCM_H
#include <linux/crypto.h>
#define AES_BLOCK_LEN 16
struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[]);
void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
u8 *b_0, u8 *aad, u8 *data, size_t data_len,
u8 *cdata, u8 *mic);
int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
u8 *mic, u8 *data);
void ieee80211_aes_key_free(struct crypto_cipher *tfm);
#endif /* AES_CCM_H */
/*
* mac80211 debugfs for wireless PHYs
*
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
*
* GPLv2
*
*/
#include <linux/debugfs.h>
#include <linux/rtnetlink.h>
#include "ieee80211_i.h"
#include "ieee80211_rate.h"
#include "debugfs.h"
int mac80211_open_file_generic(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static const char *ieee80211_mode_str(int mode)
{
switch (mode) {
case MODE_IEEE80211A:
return "IEEE 802.11a";
case MODE_IEEE80211B:
return "IEEE 802.11b";
case MODE_IEEE80211G:
return "IEEE 802.11g";
case MODE_ATHEROS_TURBO:
return "Atheros Turbo (5 GHz)";
default:
return "UNKNOWN";
}
}
static ssize_t modes_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_local *local = file->private_data;
struct ieee80211_hw_mode *mode;
char buf[150], *p = buf;
/* FIXME: locking! */
list_for_each_entry(mode, &local->modes_list, list) {
p += scnprintf(p, sizeof(buf)+buf-p,
"%s\n", ieee80211_mode_str(mode->mode));
}
return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
}
static const struct file_operations modes_ops = {
.read = modes_read,
.open = mac80211_open_file_generic,
};
#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
static ssize_t name## _read(struct file *file, char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
struct ieee80211_local *local = file->private_data; \
char buf[buflen]; \
int res; \
\
res = scnprintf(buf, buflen, fmt "\n", ##value); \
return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
} \
\
static const struct file_operations name## _ops = { \
.read = name## _read, \
.open = mac80211_open_file_generic, \
};
#define DEBUGFS_ADD(name) \
local->debugfs.name = debugfs_create_file(#name, 0444, phyd, \
local, &name## _ops);
#define DEBUGFS_DEL(name) \
debugfs_remove(local->debugfs.name); \
local->debugfs.name = NULL;
DEBUGFS_READONLY_FILE(channel, 20, "%d",
local->hw.conf.channel);
DEBUGFS_READONLY_FILE(frequency, 20, "%d",
local->hw.conf.freq);
DEBUGFS_READONLY_FILE(radar_detect, 20, "%d",
local->hw.conf.radar_detect);
DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
local->hw.conf.antenna_sel_tx);
DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
local->hw.conf.antenna_sel_rx);
DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d",
local->bridge_packets);
DEBUGFS_READONLY_FILE(key_tx_rx_threshold, 20, "%d",
local->key_tx_rx_threshold);
DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
local->rts_threshold);
DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
local->fragmentation_threshold);
DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
local->short_retry_limit);
DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
local->long_retry_limit);
DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
local->total_ps_buffered);
DEBUGFS_READONLY_FILE(mode, 20, "%s",
ieee80211_mode_str(local->hw.conf.phymode));
DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
local->wep_iv & 0xffffff);
DEBUGFS_READONLY_FILE(tx_power_reduction, 20, "%d.%d dBm",
local->hw.conf.tx_power_reduction / 10,
local->hw.conf.tx_power_reduction & 10);
DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
/* statistics stuff */
static inline int rtnl_lock_local(struct ieee80211_local *local)
{
rtnl_lock();
if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
rtnl_unlock();
return -ENODEV;
}
return 0;
}
#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \
DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
static ssize_t format_devstat_counter(struct ieee80211_local *local,
char __user *userbuf,
size_t count, loff_t *ppos,
int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
int buflen))
{
struct ieee80211_low_level_stats stats;
char buf[20];
int res;
if (!local->ops->get_stats)
return -EOPNOTSUPP;
res = rtnl_lock_local(local);
if (res)
return res;
res = local->ops->get_stats(local_to_hw(local), &stats);
rtnl_unlock();
if (!res)
res = printvalue(&stats, buf, sizeof(buf));
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
#define DEBUGFS_DEVSTATS_FILE(name) \
static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
char *buf, int buflen) \
{ \
return scnprintf(buf, buflen, "%u\n", stats->name); \
} \
static ssize_t stats_ ##name## _read(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
return format_devstat_counter(file->private_data, \
userbuf, \
count, \
ppos, \
print_devstats_##name); \
} \
\
static const struct file_operations stats_ ##name## _ops = { \
.read = stats_ ##name## _read, \
.open = mac80211_open_file_generic, \
};
#define DEBUGFS_STATS_ADD(name) \
local->debugfs.stats.name = debugfs_create_file(#name, 0444, statsd,\
local, &stats_ ##name## _ops);
#define DEBUGFS_STATS_DEL(name) \
debugfs_remove(local->debugfs.stats.name); \
local->debugfs.stats.name = NULL;
DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u",
local->dot11TransmittedFragmentCount);
DEBUGFS_STATS_FILE(multicast_transmitted_frame_count, 20, "%u",
local->dot11MulticastTransmittedFrameCount);
DEBUGFS_STATS_FILE(failed_count, 20, "%u",
local->dot11FailedCount);
DEBUGFS_STATS_FILE(retry_count, 20, "%u",
local->dot11RetryCount);
DEBUGFS_STATS_FILE(multiple_retry_count, 20, "%u",
local->dot11MultipleRetryCount);
DEBUGFS_STATS_FILE(frame_duplicate_count, 20, "%u",
local->dot11FrameDuplicateCount);
DEBUGFS_STATS_FILE(received_fragment_count, 20, "%u",
local->dot11ReceivedFragmentCount);
DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u",
local->dot11MulticastReceivedFrameCount);
DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u",
local->dot11TransmittedFrameCount);
DEBUGFS_STATS_FILE(wep_undecryptable_count, 20, "%u",
local->dot11WEPUndecryptableCount);
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u",
local->tx_handlers_drop);
DEBUGFS_STATS_FILE(tx_handlers_queued, 20, "%u",
local->tx_handlers_queued);
DEBUGFS_STATS_FILE(tx_handlers_drop_unencrypted, 20, "%u",
local->tx_handlers_drop_unencrypted);
DEBUGFS_STATS_FILE(tx_handlers_drop_fragment, 20, "%u",
local->tx_handlers_drop_fragment);
DEBUGFS_STATS_FILE(tx_handlers_drop_wep, 20, "%u",
local->tx_handlers_drop_wep);
DEBUGFS_STATS_FILE(tx_handlers_drop_not_assoc, 20, "%u",
local->tx_handlers_drop_not_assoc);
DEBUGFS_STATS_FILE(tx_handlers_drop_unauth_port, 20, "%u",
local->tx_handlers_drop_unauth_port);
DEBUGFS_STATS_FILE(rx_handlers_drop, 20, "%u",
local->rx_handlers_drop);
DEBUGFS_STATS_FILE(rx_handlers_queued, 20, "%u",
local->rx_handlers_queued);
DEBUGFS_STATS_FILE(rx_handlers_drop_nullfunc, 20, "%u",
local->rx_handlers_drop_nullfunc);
DEBUGFS_STATS_FILE(rx_handlers_drop_defrag, 20, "%u",
local->rx_handlers_drop_defrag);
DEBUGFS_STATS_FILE(rx_handlers_drop_short, 20, "%u",
local->rx_handlers_drop_short);
DEBUGFS_STATS_FILE(rx_handlers_drop_passive_scan, 20, "%u",
local->rx_handlers_drop_passive_scan);
DEBUGFS_STATS_FILE(tx_expand_skb_head, 20, "%u",
local->tx_expand_skb_head);
DEBUGFS_STATS_FILE(tx_expand_skb_head_cloned, 20, "%u",
local->tx_expand_skb_head_cloned);
DEBUGFS_STATS_FILE(rx_expand_skb_head, 20, "%u",
local->rx_expand_skb_head);
DEBUGFS_STATS_FILE(rx_expand_skb_head2, 20, "%u",
local->rx_expand_skb_head2);
DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u",
local->rx_handlers_fragments);
DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u",
local->tx_status_drop);
static ssize_t stats_wme_rx_queue_read(struct file *file,
char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_local *local = file->private_data;
char buf[NUM_RX_DATA_QUEUES*15], *p = buf;
int i;
for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
p += scnprintf(p, sizeof(buf)+buf-p,
"%u\n", local->wme_rx_queue[i]);
return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
}
static const struct file_operations stats_wme_rx_queue_ops = {
.read = stats_wme_rx_queue_read,
.open = mac80211_open_file_generic,
};
static ssize_t stats_wme_tx_queue_read(struct file *file,
char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_local *local = file->private_data;
char buf[NUM_TX_DATA_QUEUES*15], *p = buf;
int i;
for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
p += scnprintf(p, sizeof(buf)+buf-p,
"%u\n", local->wme_tx_queue[i]);
return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
}
static const struct file_operations stats_wme_tx_queue_ops = {
.read = stats_wme_tx_queue_read,
.open = mac80211_open_file_generic,
};
#endif
DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
void debugfs_hw_add(struct ieee80211_local *local)
{
struct dentry *phyd = local->hw.wiphy->debugfsdir;
struct dentry *statsd;
if (!phyd)
return;
local->debugfs.stations = debugfs_create_dir("stations", phyd);
local->debugfs.keys = debugfs_create_dir("keys", phyd);
DEBUGFS_ADD(channel);
DEBUGFS_ADD(frequency);
DEBUGFS_ADD(radar_detect);
DEBUGFS_ADD(antenna_sel_tx);
DEBUGFS_ADD(antenna_sel_rx);
DEBUGFS_ADD(bridge_packets);
DEBUGFS_ADD(key_tx_rx_threshold);
DEBUGFS_ADD(rts_threshold);
DEBUGFS_ADD(fragmentation_threshold);
DEBUGFS_ADD(short_retry_limit);
DEBUGFS_ADD(long_retry_limit);
DEBUGFS_ADD(total_ps_buffered);
DEBUGFS_ADD(mode);
DEBUGFS_ADD(wep_iv);
DEBUGFS_ADD(tx_power_reduction);
DEBUGFS_ADD(modes);
statsd = debugfs_create_dir("statistics", phyd);
local->debugfs.statistics = statsd;
/* if the dir failed, don't put all the other things into the root! */
if (!statsd)
return;
DEBUGFS_STATS_ADD(transmitted_fragment_count);
DEBUGFS_STATS_ADD(multicast_transmitted_frame_count);
DEBUGFS_STATS_ADD(failed_count);
DEBUGFS_STATS_ADD(retry_count);
DEBUGFS_STATS_ADD(multiple_retry_count);
DEBUGFS_STATS_ADD(frame_duplicate_count);
DEBUGFS_STATS_ADD(received_fragment_count);
DEBUGFS_STATS_ADD(multicast_received_frame_count);
DEBUGFS_STATS_ADD(transmitted_frame_count);
DEBUGFS_STATS_ADD(wep_undecryptable_count);
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
DEBUGFS_STATS_ADD(tx_handlers_drop);
DEBUGFS_STATS_ADD(tx_handlers_queued);
DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted);
DEBUGFS_STATS_ADD(tx_handlers_drop_fragment);
DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
DEBUGFS_STATS_ADD(rx_handlers_drop);
DEBUGFS_STATS_ADD(rx_handlers_queued);
DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
DEBUGFS_STATS_ADD(rx_handlers_drop_short);
DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan);
DEBUGFS_STATS_ADD(tx_expand_skb_head);
DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
DEBUGFS_STATS_ADD(rx_expand_skb_head);
DEBUGFS_STATS_ADD(rx_expand_skb_head2);
DEBUGFS_STATS_ADD(rx_handlers_fragments);
DEBUGFS_STATS_ADD(tx_status_drop);
DEBUGFS_STATS_ADD(wme_tx_queue);
DEBUGFS_STATS_ADD(wme_rx_queue);
#endif
DEBUGFS_STATS_ADD(dot11ACKFailureCount);
DEBUGFS_STATS_ADD(dot11RTSFailureCount);
DEBUGFS_STATS_ADD(dot11FCSErrorCount);
DEBUGFS_STATS_ADD(dot11RTSSuccessCount);
}
void debugfs_hw_del(struct ieee80211_local *local)
{
DEBUGFS_DEL(channel);
DEBUGFS_DEL(frequency);
DEBUGFS_DEL(radar_detect);
DEBUGFS_DEL(antenna_sel_tx);
DEBUGFS_DEL(antenna_sel_rx);
DEBUGFS_DEL(bridge_packets);
DEBUGFS_DEL(key_tx_rx_threshold);
DEBUGFS_DEL(rts_threshold);
DEBUGFS_DEL(fragmentation_threshold);
DEBUGFS_DEL(short_retry_limit);
DEBUGFS_DEL(long_retry_limit);
DEBUGFS_DEL(total_ps_buffered);
DEBUGFS_DEL(mode);
DEBUGFS_DEL(wep_iv);
DEBUGFS_DEL(tx_power_reduction);
DEBUGFS_DEL(modes);
DEBUGFS_STATS_DEL(transmitted_fragment_count);
DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
DEBUGFS_STATS_DEL(failed_count);
DEBUGFS_STATS_DEL(retry_count);
DEBUGFS_STATS_DEL(multiple_retry_count);
DEBUGFS_STATS_DEL(frame_duplicate_count);
DEBUGFS_STATS_DEL(received_fragment_count);
DEBUGFS_STATS_DEL(multicast_received_frame_count);
DEBUGFS_STATS_DEL(transmitted_frame_count);
DEBUGFS_STATS_DEL(wep_undecryptable_count);
DEBUGFS_STATS_DEL(num_scans);
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
DEBUGFS_STATS_DEL(tx_handlers_drop);
DEBUGFS_STATS_DEL(tx_handlers_queued);
DEBUGFS_STATS_DEL(tx_handlers_drop_unencrypted);
DEBUGFS_STATS_DEL(tx_handlers_drop_fragment);
DEBUGFS_STATS_DEL(tx_handlers_drop_wep);
DEBUGFS_STATS_DEL(tx_handlers_drop_not_assoc);
DEBUGFS_STATS_DEL(tx_handlers_drop_unauth_port);
DEBUGFS_STATS_DEL(rx_handlers_drop);
DEBUGFS_STATS_DEL(rx_handlers_queued);
DEBUGFS_STATS_DEL(rx_handlers_drop_nullfunc);
DEBUGFS_STATS_DEL(rx_handlers_drop_defrag);
DEBUGFS_STATS_DEL(rx_handlers_drop_short);
DEBUGFS_STATS_DEL(rx_handlers_drop_passive_scan);
DEBUGFS_STATS_DEL(tx_expand_skb_head);
DEBUGFS_STATS_DEL(tx_expand_skb_head_cloned);
DEBUGFS_STATS_DEL(rx_expand_skb_head);
DEBUGFS_STATS_DEL(rx_expand_skb_head2);
DEBUGFS_STATS_DEL(rx_handlers_fragments);
DEBUGFS_STATS_DEL(tx_status_drop);
DEBUGFS_STATS_DEL(wme_tx_queue);
DEBUGFS_STATS_DEL(wme_rx_queue);
#endif
DEBUGFS_STATS_DEL(dot11ACKFailureCount);
DEBUGFS_STATS_DEL(dot11RTSFailureCount);
DEBUGFS_STATS_DEL(dot11FCSErrorCount);
DEBUGFS_STATS_DEL(dot11RTSSuccessCount);
debugfs_remove(local->debugfs.statistics);
local->debugfs.statistics = NULL;
debugfs_remove(local->debugfs.stations);
local->debugfs.stations = NULL;
debugfs_remove(local->debugfs.keys);
local->debugfs.keys = NULL;
}
#ifndef __MAC80211_DEBUGFS_H
#define __MAC80211_DEBUGFS_H
#ifdef CONFIG_MAC80211_DEBUGFS
extern void debugfs_hw_add(struct ieee80211_local *local);
extern void debugfs_hw_del(struct ieee80211_local *local);
extern int mac80211_open_file_generic(struct inode *inode, struct file *file);
#else
static inline void debugfs_hw_add(struct ieee80211_local *local)
{
return;
}
static inline void debugfs_hw_del(struct ieee80211_local *local) {}
#endif
#endif /* __MAC80211_DEBUGFS_H */
/*
* Copyright 2003-2005 Devicescape Software, Inc.
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kobject.h>
#include "ieee80211_i.h"
#include "ieee80211_key.h"
#include "debugfs.h"
#include "debugfs_key.h"
#define KEY_READ(name, buflen, format_string) \
static ssize_t key_##name##_read(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
char buf[buflen]; \
struct ieee80211_key *key = file->private_data; \
int res = scnprintf(buf, buflen, format_string, key->name); \
return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
}
#define KEY_READ_D(name) KEY_READ(name, 20, "%d\n")
#define KEY_OPS(name) \
static const struct file_operations key_ ##name## _ops = { \
.read = key_##name##_read, \
.open = mac80211_open_file_generic, \
}
#define KEY_FILE(name, format) \
KEY_READ_##format(name) \
KEY_OPS(name)
KEY_FILE(keylen, D);
KEY_FILE(force_sw_encrypt, D);
KEY_FILE(keyidx, D);
KEY_FILE(hw_key_idx, D);
KEY_FILE(tx_rx_count, D);
static ssize_t key_algorithm_read(struct file *file,
char __user *userbuf,
size_t count, loff_t *ppos)
{
char *alg;
struct ieee80211_key *key = file->private_data;
switch (key->alg) {
case ALG_WEP:
alg = "WEP\n";
break;
case ALG_TKIP:
alg = "TKIP\n";
break;
case ALG_CCMP:
alg = "CCMP\n";
break;
default:
return 0;
}
return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg));
}
KEY_OPS(algorithm);
static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
const u8 *tpn;
char buf[20];
int len;
struct ieee80211_key *key = file->private_data;
switch (key->alg) {
case ALG_WEP:
len = scnprintf(buf, sizeof(buf), "\n");
case ALG_TKIP:
len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
key->u.tkip.iv32,
key->u.tkip.iv16);
case ALG_CCMP:
tpn = key->u.ccmp.tx_pn;
len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
default:
return 0;
}
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
KEY_OPS(tx_spec);
static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_key *key = file->private_data;
char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
int i, len;
const u8 *rpn;
switch (key->alg) {
case ALG_WEP:
len = scnprintf(buf, sizeof(buf), "\n");
case ALG_TKIP:
for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
p += scnprintf(p, sizeof(buf)+buf-p,
"%08x %04x\n",
key->u.tkip.iv32_rx[i],
key->u.tkip.iv16_rx[i]);
len = p - buf;
case ALG_CCMP:
for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
rpn = key->u.ccmp.rx_pn[i];
p += scnprintf(p, sizeof(buf)+buf-p,
"%02x%02x%02x%02x%02x%02x\n",
rpn[0], rpn[1], rpn[2],
rpn[3], rpn[4], rpn[5]);
}
len = p - buf;
default:
return 0;
}
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
KEY_OPS(rx_spec);
static ssize_t key_replays_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_key *key = file->private_data;
char buf[20];
int len;
if (key->alg != ALG_CCMP)
return 0;
len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
KEY_OPS(replays);
static ssize_t key_key_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_key *key = file->private_data;
int i, res, bufsize = 2*key->keylen+2;
char *buf = kmalloc(bufsize, GFP_KERNEL);
char *p = buf;
for (i = 0; i < key->keylen; i++)
p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]);
p += scnprintf(p, bufsize+buf-p, "\n");
res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
kfree(buf);
return res;
}
KEY_OPS(key);
#define DEBUGFS_ADD(name) \
key->debugfs.name = debugfs_create_file(#name, 0400,\
key->debugfs.dir, key, &key_##name##_ops);
void ieee80211_debugfs_key_add(struct ieee80211_local *local,
struct ieee80211_key *key)
{
char buf[20];
if (!local->debugfs.keys)
return;
sprintf(buf, "%d", key->keyidx);
key->debugfs.dir = debugfs_create_dir(buf,
local->debugfs.keys);
if (!key->debugfs.dir)
return;
DEBUGFS_ADD(keylen);
DEBUGFS_ADD(force_sw_encrypt);
DEBUGFS_ADD(keyidx);
DEBUGFS_ADD(hw_key_idx);
DEBUGFS_ADD(tx_rx_count);
DEBUGFS_ADD(algorithm);
DEBUGFS_ADD(tx_spec);
DEBUGFS_ADD(rx_spec);
DEBUGFS_ADD(replays);
DEBUGFS_ADD(key);
};
#define DEBUGFS_DEL(name) \
debugfs_remove(key->debugfs.name); key->debugfs.name = NULL;
void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
{
if (!key)
return;
DEBUGFS_DEL(keylen);
DEBUGFS_DEL(force_sw_encrypt);
DEBUGFS_DEL(keyidx);
DEBUGFS_DEL(hw_key_idx);
DEBUGFS_DEL(tx_rx_count);
DEBUGFS_DEL(algorithm);
DEBUGFS_DEL(tx_spec);
DEBUGFS_DEL(rx_spec);
DEBUGFS_DEL(replays);
DEBUGFS_DEL(key);
debugfs_remove(key->debugfs.stalink);
key->debugfs.stalink = NULL;
debugfs_remove(key->debugfs.dir);
key->debugfs.dir = NULL;
}
void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
{
char buf[50];
if (!sdata->debugfsdir)
return;
sprintf(buf, "../keys/%d", sdata->default_key->keyidx);
sdata->debugfs.default_key =
debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
}
void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
{
if (!sdata)
return;
debugfs_remove(sdata->debugfs.default_key);
sdata->debugfs.default_key = NULL;
}
void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
struct sta_info *sta)
{
char buf[50];
if (!key->debugfs.dir)
return;
sprintf(buf, "../sta/" MAC_FMT, MAC_ARG(sta->addr));
key->debugfs.stalink =
debugfs_create_symlink("station", key->debugfs.dir, buf);
}
void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta)
{
debugfs_remove(key->debugfs.stalink);
key->debugfs.stalink = NULL;
}
#ifndef __MAC80211_DEBUGFS_KEY_H
#define __MAC80211_DEBUGFS_KEY_H
#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_debugfs_key_add(struct ieee80211_local *local,
struct ieee80211_key *key);
void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
struct sta_info *sta);
void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta);
#else
static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local,
struct ieee80211_key *key)
{}
static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
{}
static inline void ieee80211_debugfs_key_add_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_remove_default(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_key_sta_link(
struct ieee80211_key *key, struct sta_info *sta)
{}
static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
struct sta_info *sta)
{}
#endif
#endif /* __MAC80211_DEBUGFS_KEY_H */
/*
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/if.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
#include <net/mac80211.h>
#include <net/cfg80211.h>
#include "ieee80211_i.h"
#include "ieee80211_rate.h"
#include "debugfs.h"
#include "debugfs_netdev.h"
static ssize_t ieee80211_if_read(
struct ieee80211_sub_if_data *sdata,
char __user *userbuf,
size_t count, loff_t *ppos,
ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
{
char buf[70];
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
if (sdata->dev->reg_state == NETREG_REGISTERED) {
ret = (*format)(sdata, buf, sizeof(buf));
ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
}
read_unlock(&dev_base_lock);
return ret;
}
#define IEEE80211_IF_FMT(name, field, format_string) \
static ssize_t ieee80211_if_fmt_##name( \
const struct ieee80211_sub_if_data *sdata, char *buf, \
int buflen) \
{ \
return scnprintf(buf, buflen, format_string, sdata->field); \
}
#define IEEE80211_IF_FMT_DEC(name, field) \
IEEE80211_IF_FMT(name, field, "%d\n")
#define IEEE80211_IF_FMT_HEX(name, field) \
IEEE80211_IF_FMT(name, field, "%#x\n")
#define IEEE80211_IF_FMT_SIZE(name, field) \
IEEE80211_IF_FMT(name, field, "%zd\n")
#define IEEE80211_IF_FMT_ATOMIC(name, field) \
static ssize_t ieee80211_if_fmt_##name( \
const struct ieee80211_sub_if_data *sdata, \
char *buf, int buflen) \
{ \
return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
}
#define IEEE80211_IF_FMT_MAC(name, field) \
static ssize_t ieee80211_if_fmt_##name( \
const struct ieee80211_sub_if_data *sdata, char *buf, \
int buflen) \
{ \
return scnprintf(buf, buflen, MAC_FMT "\n", MAC_ARG(sdata->field));\
}
#define __IEEE80211_IF_FILE(name) \
static ssize_t ieee80211_if_read_##name(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
return ieee80211_if_read(file->private_data, \
userbuf, count, ppos, \
ieee80211_if_fmt_##name); \
} \
static const struct file_operations name##_ops = { \
.read = ieee80211_if_read_##name, \
.open = mac80211_open_file_generic, \
}
#define IEEE80211_IF_FILE(name, field, format) \
IEEE80211_IF_FMT_##format(name, field) \
__IEEE80211_IF_FILE(name)
/* common attributes */
IEEE80211_IF_FILE(channel_use, channel_use, DEC);
IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
IEEE80211_IF_FILE(eapol, eapol, DEC);
IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC);
/* STA/IBSS attributes */
IEEE80211_IF_FILE(state, u.sta.state, DEC);
IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
static ssize_t ieee80211_if_fmt_flags(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{
return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
sdata->u.sta.ssid_set ? "SSID\n" : "",
sdata->u.sta.bssid_set ? "BSSID\n" : "",
sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
sdata->u.sta.authenticated ? "AUTH\n" : "",
sdata->u.sta.associated ? "ASSOC\n" : "",
sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
sdata->u.sta.use_protection ? "CTS prot\n" : "");
}
__IEEE80211_IF_FILE(flags);
/* AP attributes */
IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC);
IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
static ssize_t ieee80211_if_fmt_num_buffered_multicast(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{
return scnprintf(buf, buflen, "%u\n",
skb_queue_len(&sdata->u.ap.ps_bc_buf));
}
__IEEE80211_IF_FILE(num_buffered_multicast);
static ssize_t ieee80211_if_fmt_beacon_head_len(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{
if (sdata->u.ap.beacon_head)
return scnprintf(buf, buflen, "%d\n",
sdata->u.ap.beacon_head_len);
return scnprintf(buf, buflen, "\n");
}
__IEEE80211_IF_FILE(beacon_head_len);
static ssize_t ieee80211_if_fmt_beacon_tail_len(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{
if (sdata->u.ap.beacon_tail)
return scnprintf(buf, buflen, "%d\n",
sdata->u.ap.beacon_tail_len);
return scnprintf(buf, buflen, "\n");
}
__IEEE80211_IF_FILE(beacon_tail_len);
/* WDS attributes */
IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
/* VLAN attributes */
IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
/* MONITOR attributes */
static ssize_t ieee80211_if_fmt_mode(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{
struct ieee80211_local *local = sdata->local;
return scnprintf(buf, buflen, "%s\n",
((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
local->open_count == local->monitors) ?
"hard" : "soft");
}
__IEEE80211_IF_FILE(mode);
#define DEBUGFS_ADD(name, type)\
sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
sdata->debugfsdir, sdata, &name##_ops);
static void add_sta_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(channel_use, sta);
DEBUGFS_ADD(drop_unencrypted, sta);
DEBUGFS_ADD(eapol, sta);
DEBUGFS_ADD(ieee8021_x, sta);
DEBUGFS_ADD(state, sta);
DEBUGFS_ADD(bssid, sta);
DEBUGFS_ADD(prev_bssid, sta);
DEBUGFS_ADD(ssid_len, sta);
DEBUGFS_ADD(aid, sta);
DEBUGFS_ADD(ap_capab, sta);
DEBUGFS_ADD(capab, sta);
DEBUGFS_ADD(extra_ie_len, sta);
DEBUGFS_ADD(auth_tries, sta);
DEBUGFS_ADD(assoc_tries, sta);
DEBUGFS_ADD(auth_algs, sta);
DEBUGFS_ADD(auth_alg, sta);
DEBUGFS_ADD(auth_transaction, sta);
DEBUGFS_ADD(flags, sta);
}
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(channel_use, ap);
DEBUGFS_ADD(drop_unencrypted, ap);
DEBUGFS_ADD(eapol, ap);
DEBUGFS_ADD(ieee8021_x, ap);
DEBUGFS_ADD(num_sta_ps, ap);
DEBUGFS_ADD(dtim_period, ap);
DEBUGFS_ADD(dtim_count, ap);
DEBUGFS_ADD(num_beacons, ap);
DEBUGFS_ADD(force_unicast_rateidx, ap);
DEBUGFS_ADD(max_ratectrl_rateidx, ap);
DEBUGFS_ADD(num_buffered_multicast, ap);
DEBUGFS_ADD(beacon_head_len, ap);
DEBUGFS_ADD(beacon_tail_len, ap);
}
static void add_wds_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(channel_use, wds);
DEBUGFS_ADD(drop_unencrypted, wds);
DEBUGFS_ADD(eapol, wds);
DEBUGFS_ADD(ieee8021_x, wds);
DEBUGFS_ADD(peer, wds);
}
static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(channel_use, vlan);
DEBUGFS_ADD(drop_unencrypted, vlan);
DEBUGFS_ADD(eapol, vlan);
DEBUGFS_ADD(ieee8021_x, vlan);
DEBUGFS_ADD(vlan_id, vlan);
}
static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(mode, monitor);
}
static void add_files(struct ieee80211_sub_if_data *sdata)
{
if (!sdata->debugfsdir)
return;
switch (sdata->type) {
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
add_sta_files(sdata);
break;
case IEEE80211_IF_TYPE_AP:
add_ap_files(sdata);
break;
case IEEE80211_IF_TYPE_WDS:
add_wds_files(sdata);
break;
case IEEE80211_IF_TYPE_MNTR:
add_monitor_files(sdata);
break;
case IEEE80211_IF_TYPE_VLAN:
add_vlan_files(sdata);
break;
default:
break;
}
}
#define DEBUGFS_DEL(name, type)\
debugfs_remove(sdata->debugfs.type.name);\
sdata->debugfs.type.name = NULL;
static void del_sta_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(channel_use, sta);
DEBUGFS_DEL(drop_unencrypted, sta);
DEBUGFS_DEL(eapol, sta);
DEBUGFS_DEL(ieee8021_x, sta);
DEBUGFS_DEL(state, sta);
DEBUGFS_DEL(bssid, sta);
DEBUGFS_DEL(prev_bssid, sta);
DEBUGFS_DEL(ssid_len, sta);
DEBUGFS_DEL(aid, sta);
DEBUGFS_DEL(ap_capab, sta);
DEBUGFS_DEL(capab, sta);
DEBUGFS_DEL(extra_ie_len, sta);
DEBUGFS_DEL(auth_tries, sta);
DEBUGFS_DEL(assoc_tries, sta);
DEBUGFS_DEL(auth_algs, sta);
DEBUGFS_DEL(auth_alg, sta);
DEBUGFS_DEL(auth_transaction, sta);
DEBUGFS_DEL(flags, sta);
}
static void del_ap_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(channel_use, ap);
DEBUGFS_DEL(drop_unencrypted, ap);
DEBUGFS_DEL(eapol, ap);
DEBUGFS_DEL(ieee8021_x, ap);
DEBUGFS_DEL(num_sta_ps, ap);
DEBUGFS_DEL(dtim_period, ap);
DEBUGFS_DEL(dtim_count, ap);
DEBUGFS_DEL(num_beacons, ap);
DEBUGFS_DEL(force_unicast_rateidx, ap);
DEBUGFS_DEL(max_ratectrl_rateidx, ap);
DEBUGFS_DEL(num_buffered_multicast, ap);
DEBUGFS_DEL(beacon_head_len, ap);
DEBUGFS_DEL(beacon_tail_len, ap);
}
static void del_wds_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(channel_use, wds);
DEBUGFS_DEL(drop_unencrypted, wds);
DEBUGFS_DEL(eapol, wds);
DEBUGFS_DEL(ieee8021_x, wds);
DEBUGFS_DEL(peer, wds);
}
static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(channel_use, vlan);
DEBUGFS_DEL(drop_unencrypted, vlan);
DEBUGFS_DEL(eapol, vlan);
DEBUGFS_DEL(ieee8021_x, vlan);
DEBUGFS_DEL(vlan_id, vlan);
}
static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(mode, monitor);
}
static void del_files(struct ieee80211_sub_if_data *sdata, int type)
{
if (!sdata->debugfsdir)
return;
switch (type) {
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
del_sta_files(sdata);
break;
case IEEE80211_IF_TYPE_AP:
del_ap_files(sdata);
break;
case IEEE80211_IF_TYPE_WDS:
del_wds_files(sdata);
break;
case IEEE80211_IF_TYPE_MNTR:
del_monitor_files(sdata);
break;
case IEEE80211_IF_TYPE_VLAN:
del_vlan_files(sdata);
break;
default:
break;
}
}
static int notif_registered;
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
{
char buf[10+IFNAMSIZ];
if (!notif_registered)
return;
sprintf(buf, "netdev:%s", sdata->dev->name);
sdata->debugfsdir = debugfs_create_dir(buf,
sdata->local->hw.wiphy->debugfsdir);
}
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
{
del_files(sdata, sdata->type);
debugfs_remove(sdata->debugfsdir);
sdata->debugfsdir = NULL;
}
void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
int oldtype)
{
del_files(sdata, oldtype);
add_files(sdata);
}
static int netdev_notify(struct notifier_block * nb,
unsigned long state,
void *ndev)
{
struct net_device *dev = ndev;
char buf[10+IFNAMSIZ];
if (state != NETDEV_CHANGENAME)
return 0;
if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
return 0;
if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
return 0;
/* TODO
sprintf(buf, "netdev:%s", dev->name);
debugfs_rename(IEEE80211_DEV_TO_SUB_IF(dev)->debugfsdir, buf);
*/
return 0;
}
static struct notifier_block mac80211_debugfs_netdev_notifier = {
.notifier_call = netdev_notify,
};
void ieee80211_debugfs_netdev_init(void)
{
int err;
err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
if (err) {
printk(KERN_ERR
"mac80211: failed to install netdev notifier,"
" disabling per-netdev debugfs!\n");
} else
notif_registered = 1;
}
void ieee80211_debugfs_netdev_exit(void)
{
unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
notif_registered = 0;
}
/* routines exported for debugfs handling */
#ifndef __IEEE80211_DEBUGFS_NETDEV_H
#define __IEEE80211_DEBUGFS_NETDEV_H
#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
int oldtype);
void ieee80211_debugfs_netdev_init(void);
void ieee80211_debugfs_netdev_exit(void);
#else
static inline void ieee80211_debugfs_add_netdev(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_remove_netdev(
struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_debugfs_change_if_type(
struct ieee80211_sub_if_data *sdata, int oldtype)
{}
static inline void ieee80211_debugfs_netdev_init(void)
{}
static inline void ieee80211_debugfs_netdev_exit(void)
{}
#endif
#endif /* __IEEE80211_DEBUGFS_NETDEV_H */
/*
* Copyright 2003-2005 Devicescape Software, Inc.
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/debugfs.h>
#include <linux/ieee80211.h>
#include "ieee80211_i.h"
#include "debugfs.h"
#include "debugfs_sta.h"
#include "sta_info.h"
/* sta attributtes */
#define STA_READ(name, buflen, field, format_string) \
static ssize_t sta_ ##name## _read(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
int res; \
struct sta_info *sta = file->private_data; \
char buf[buflen]; \
res = scnprintf(buf, buflen, format_string, sta->field); \
return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
}
#define STA_READ_D(name, field) STA_READ(name, 20, field, "%d\n")
#define STA_READ_U(name, field) STA_READ(name, 20, field, "%u\n")
#define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
#define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
#define STA_READ_RATE(name, field) \
static ssize_t sta_##name##_read(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
struct sta_info *sta = file->private_data; \
struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\
struct ieee80211_hw_mode *mode = local->oper_hw_mode; \
char buf[20]; \
int res = scnprintf(buf, sizeof(buf), "%d\n", \
(sta->field >= 0 && \
sta->field < mode->num_rates) ? \
mode->rates[sta->field].rate : -1); \
return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
}
#define STA_OPS(name) \
static const struct file_operations sta_ ##name## _ops = { \
.read = sta_##name##_read, \
.open = mac80211_open_file_generic, \
}
#define STA_FILE(name, field, format) \
STA_READ_##format(name, field) \
STA_OPS(name)
STA_FILE(aid, aid, D);
STA_FILE(key_idx_compression, key_idx_compression, D);
STA_FILE(dev, dev->name, S);
STA_FILE(vlan_id, vlan_id, D);
STA_FILE(rx_packets, rx_packets, LU);
STA_FILE(tx_packets, tx_packets, LU);
STA_FILE(rx_bytes, rx_bytes, LU);
STA_FILE(tx_bytes, tx_bytes, LU);
STA_FILE(rx_duplicates, num_duplicates, LU);
STA_FILE(rx_fragments, rx_fragments, LU);
STA_FILE(rx_dropped, rx_dropped, LU);
STA_FILE(tx_fragments, tx_fragments, LU);
STA_FILE(tx_filtered, tx_filtered_count, LU);
STA_FILE(txrate, txrate, RATE);
STA_FILE(last_txrate, last_txrate, RATE);
STA_FILE(tx_retry_failed, tx_retry_failed, LU);
STA_FILE(tx_retry_count, tx_retry_count, LU);
STA_FILE(last_rssi, last_rssi, D);
STA_FILE(last_signal, last_signal, D);
STA_FILE(last_noise, last_noise, D);
STA_FILE(channel_use, channel_use, D);
STA_FILE(wep_weak_iv_count, wep_weak_iv_count, D);
static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[100];
struct sta_info *sta = file->private_data;
int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
sta->flags & WLAN_STA_PS ? "PS\n" : "",
sta->flags & WLAN_STA_TIM ? "TIM\n" : "",
sta->flags & WLAN_STA_PERM ? "PERM\n" : "",
sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
sta->flags & WLAN_STA_WME ? "WME\n" : "",
sta->flags & WLAN_STA_WDS ? "WDS\n" : "");
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
STA_OPS(flags);
static ssize_t sta_num_ps_buf_frames_read(struct file *file,
char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[20];
struct sta_info *sta = file->private_data;
int res = scnprintf(buf, sizeof(buf), "%u\n",
skb_queue_len(&sta->ps_tx_buf));
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
STA_OPS(num_ps_buf_frames);
static ssize_t sta_last_ack_rssi_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[100];
struct sta_info *sta = file->private_data;
int res = scnprintf(buf, sizeof(buf), "%d %d %d\n",
sta->last_ack_rssi[0],
sta->last_ack_rssi[1],
sta->last_ack_rssi[2]);
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
STA_OPS(last_ack_rssi);
static ssize_t sta_last_ack_ms_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[20];
struct sta_info *sta = file->private_data;
int res = scnprintf(buf, sizeof(buf), "%d\n",
sta->last_ack ?
jiffies_to_msecs(jiffies - sta->last_ack) : -1);
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
STA_OPS(last_ack_ms);
static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[20];
struct sta_info *sta = file->private_data;
int res = scnprintf(buf, sizeof(buf), "%d\n",
jiffies_to_msecs(jiffies - sta->last_rx));
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
STA_OPS(inactive_ms);
static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
int i;
struct sta_info *sta = file->private_data;
for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%x ",
sta->last_seq_ctrl[i]);
p += scnprintf(p, sizeof(buf)+buf-p, "\n");
return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
}
STA_OPS(last_seq_ctrl);
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
static ssize_t sta_wme_rx_queue_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
int i;
struct sta_info *sta = file->private_data;
for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
sta->wme_rx_queue[i]);
p += scnprintf(p, sizeof(buf)+buf-p, "\n");
return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
}
STA_OPS(wme_rx_queue);
static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[15*NUM_TX_DATA_QUEUES], *p = buf;
int i;
struct sta_info *sta = file->private_data;
for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
sta->wme_tx_queue[i]);
p += scnprintf(p, sizeof(buf)+buf-p, "\n");
return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
}
STA_OPS(wme_tx_queue);
#endif
#define DEBUGFS_ADD(name) \
sta->debugfs.name = debugfs_create_file(#name, 0444, \
sta->debugfs.dir, sta, &sta_ ##name## _ops);
#define DEBUGFS_DEL(name) \
debugfs_remove(sta->debugfs.name);\
sta->debugfs.name = NULL;
void ieee80211_sta_debugfs_add(struct sta_info *sta)
{
char buf[3*6];
struct dentry *stations_dir = sta->local->debugfs.stations;
if (!stations_dir)
return;
sprintf(buf, MAC_FMT, MAC_ARG(sta->addr));
sta->debugfs.dir = debugfs_create_dir(buf, stations_dir);
if (!sta->debugfs.dir)
return;
DEBUGFS_ADD(flags);
DEBUGFS_ADD(num_ps_buf_frames);
DEBUGFS_ADD(last_ack_rssi);
DEBUGFS_ADD(last_ack_ms);
DEBUGFS_ADD(inactive_ms);
DEBUGFS_ADD(last_seq_ctrl);
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
DEBUGFS_ADD(wme_rx_queue);
DEBUGFS_ADD(wme_tx_queue);
#endif
}
void ieee80211_sta_debugfs_remove(struct sta_info *sta)
{
DEBUGFS_DEL(flags);
DEBUGFS_DEL(num_ps_buf_frames);
DEBUGFS_DEL(last_ack_rssi);
DEBUGFS_DEL(last_ack_ms);
DEBUGFS_DEL(inactive_ms);
DEBUGFS_DEL(last_seq_ctrl);
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
DEBUGFS_DEL(wme_rx_queue);
DEBUGFS_DEL(wme_tx_queue);
#endif
debugfs_remove(sta->debugfs.dir);
sta->debugfs.dir = NULL;
}
#ifndef __MAC80211_DEBUGFS_STA_H
#define __MAC80211_DEBUGFS_STA_H
#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_sta_debugfs_add(struct sta_info *sta);
void ieee80211_sta_debugfs_remove(struct sta_info *sta);
#else
static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {}
static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {}
#endif
#endif /* __MAC80211_DEBUGFS_STA_H */
/*
* Host AP (software wireless LAN access point) user space daemon for
* Host AP kernel driver
* Copyright 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
* Copyright 2002-2004, Instant802 Networks, Inc.
* Copyright 2005, Devicescape Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef HOSTAPD_IOCTL_H
#define HOSTAPD_IOCTL_H
#ifdef __KERNEL__
#include <linux/types.h>
#endif /* __KERNEL__ */
#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
#define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3)
/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes:
* This table is no longer added to, the whole sub-ioctl
* mess shall be deleted completely. */
enum {
PRISM2_PARAM_IEEE_802_1X = 23,
PRISM2_PARAM_ANTSEL_TX = 24,
PRISM2_PARAM_ANTSEL_RX = 25,
/* Instant802 additions */
PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001,
PRISM2_PARAM_DROP_UNENCRYPTED = 1002,
PRISM2_PARAM_PREAMBLE = 1003,
PRISM2_PARAM_SHORT_SLOT_TIME = 1006,
PRISM2_PARAM_NEXT_MODE = 1008,
PRISM2_PARAM_CLEAR_KEYS = 1009,
PRISM2_PARAM_RADIO_ENABLED = 1010,
PRISM2_PARAM_ANTENNA_MODE = 1013,
PRISM2_PARAM_STAT_TIME = 1016,
PRISM2_PARAM_STA_ANTENNA_SEL = 1017,
PRISM2_PARAM_FORCE_UNICAST_RATE = 1018,
PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019,
PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020,
PRISM2_PARAM_MAX_RATECTRL_RATE = 1021,
PRISM2_PARAM_TX_POWER_REDUCTION = 1022,
PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024,
PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026,
PRISM2_PARAM_WIFI_WME_NOACK_TEST = 1033,
PRISM2_PARAM_SCAN_FLAGS = 1035,
PRISM2_PARAM_HW_MODES = 1036,
PRISM2_PARAM_CREATE_IBSS = 1037,
PRISM2_PARAM_WMM_ENABLED = 1038,
PRISM2_PARAM_MIXED_CELL = 1039,
PRISM2_PARAM_RADAR_DETECT = 1043,
PRISM2_PARAM_SPECTRUM_MGMT = 1044,
};
enum {
IEEE80211_KEY_MGMT_NONE = 0,
IEEE80211_KEY_MGMT_IEEE8021X = 1,
IEEE80211_KEY_MGMT_WPA_PSK = 2,
IEEE80211_KEY_MGMT_WPA_EAP = 3,
};
/* Data structures used for get_hw_features ioctl */
struct hostapd_ioctl_hw_modes_hdr {
int mode;
int num_channels;
int num_rates;
};
struct ieee80211_channel_data {
short chan; /* channel number (IEEE 802.11) */
short freq; /* frequency in MHz */
int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
};
struct ieee80211_rate_data {
int rate; /* rate in 100 kbps */
int flags; /* IEEE80211_RATE_ flags */
};
/* ADD_IF, REMOVE_IF, and UPDATE_IF 'type' argument */
enum {
HOSTAP_IF_WDS = 1, HOSTAP_IF_VLAN = 2, HOSTAP_IF_BSS = 3,
HOSTAP_IF_STA = 4
};
struct hostapd_if_wds {
u8 remote_addr[ETH_ALEN];
};
struct hostapd_if_vlan {
u8 id;
};
struct hostapd_if_bss {
u8 bssid[ETH_ALEN];
};
struct hostapd_if_sta {
};
#endif /* HOSTAPD_IOCTL_H */
此差异已折叠。
/*
* mac80211 configuration hooks for cfg80211
*
* Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
*
* This file is GPLv2 as found in COPYING.
*/
#include <linux/nl80211.h>
#include <linux/rtnetlink.h>
#include <net/cfg80211.h>
#include "ieee80211_i.h"
#include "ieee80211_cfg.h"
static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
unsigned int type)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
int itype;
if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
return -ENODEV;
switch (type) {
case NL80211_IFTYPE_UNSPECIFIED:
itype = IEEE80211_IF_TYPE_STA;
break;
case NL80211_IFTYPE_ADHOC:
itype = IEEE80211_IF_TYPE_IBSS;
break;
case NL80211_IFTYPE_STATION:
itype = IEEE80211_IF_TYPE_STA;
break;
case NL80211_IFTYPE_MONITOR:
itype = IEEE80211_IF_TYPE_MNTR;
break;
default:
return -EINVAL;
}
return ieee80211_if_add(local->mdev, name, NULL, itype);
}
static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct net_device *dev;
char *name;
if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
return -ENODEV;
dev = dev_get_by_index(ifindex);
if (!dev)
return 0;
name = dev->name;
dev_put(dev);
return ieee80211_if_remove(local->mdev, name, -1);
}
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
};
/*
* mac80211 configuration hooks for cfg80211
*/
#ifndef __IEEE80211_CFG_H
#define __IEEE80211_CFG_H
extern struct cfg80211_ops mac80211_config_ops;
#endif /* __IEEE80211_CFG_H */
/*
* IEEE 802.11 driver (80211.o) -- hostapd interface
* Copyright 2002-2004, Instant802 Networks, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef IEEE80211_COMMON_H
#define IEEE80211_COMMON_H
#include <linux/types.h>
/*
* This is common header information with user space. It is used on all
* frames sent to wlan#ap interface.
*/
#define IEEE80211_FI_VERSION 0x80211001
struct ieee80211_frame_info {
__be32 version;
__be32 length;
__be64 mactime;
__be64 hosttime;
__be32 phytype;
__be32 channel;
__be32 datarate;
__be32 antenna;
__be32 priority;
__be32 ssi_type;
__be32 ssi_signal;
__be32 ssi_noise;
__be32 preamble;
__be32 encoding;
/* Note: this structure is otherwise identical to capture format used
* in linux-wlan-ng, but this additional field is used to provide meta
* data about the frame to hostapd. This was the easiest method for
* providing this information, but this might change in the future. */
__be32 msg_type;
} __attribute__ ((packed));
enum ieee80211_msg_type {
ieee80211_msg_normal = 0,
ieee80211_msg_tx_callback_ack = 1,
ieee80211_msg_tx_callback_fail = 2,
ieee80211_msg_passive_scan = 3,
ieee80211_msg_wep_frame_unknown_key = 4,
ieee80211_msg_michael_mic_failure = 5,
/* hole at 6, was monitor but never sent to userspace */
ieee80211_msg_sta_not_assoc = 7,
ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */,
ieee80211_msg_key_threshold_notification = 9,
ieee80211_msg_radar = 11,
};
struct ieee80211_msg_set_aid_for_sta {
char sta_address[ETH_ALEN];
u16 aid;
};
struct ieee80211_msg_key_notification {
int tx_rx_count;
char ifname[IFNAMSIZ];
u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast keys */
};
enum ieee80211_phytype {
ieee80211_phytype_fhss_dot11_97 = 1,
ieee80211_phytype_dsss_dot11_97 = 2,
ieee80211_phytype_irbaseband = 3,
ieee80211_phytype_dsss_dot11_b = 4,
ieee80211_phytype_pbcc_dot11_b = 5,
ieee80211_phytype_ofdm_dot11_g = 6,
ieee80211_phytype_pbcc_dot11_g = 7,
ieee80211_phytype_ofdm_dot11_a = 8,
ieee80211_phytype_dsss_dot11_turbog = 255,
ieee80211_phytype_dsss_dot11_turbo = 256,
};
enum ieee80211_ssi_type {
ieee80211_ssi_none = 0,
ieee80211_ssi_norm = 1, /* normalized, 0-1000 */
ieee80211_ssi_dbm = 2,
ieee80211_ssi_raw = 3, /* raw SSI */
};
struct ieee80211_radar_info {
int channel;
int radar;
int radar_type;
};
#endif /* IEEE80211_COMMON_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* Copyright 2002-2004, Instant802 Networks, Inc.
* Copyright 2005, Devicescape Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef IEEE80211_KEY_H
#define IEEE80211_KEY_H
#include <linux/types.h>
#include <linux/kref.h>
#include <linux/crypto.h>
#include <net/mac80211.h>
/* ALG_TKIP
* struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
* Temporal Encryption Key (128 bits)
* Temporal Authenticator Tx MIC Key (64 bits)
* Temporal Authenticator Rx MIC Key (64 bits)
*/
#define WEP_IV_LEN 4
#define WEP_ICV_LEN 4
#define ALG_TKIP_KEY_LEN 32
/* Starting offsets for each key */
#define ALG_TKIP_TEMP_ENCR_KEY 0
#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
#define TKIP_IV_LEN 8
#define TKIP_ICV_LEN 4
#define ALG_CCMP_KEY_LEN 16
#define CCMP_HDR_LEN 8
#define CCMP_MIC_LEN 8
#define CCMP_TK_LEN 16
#define CCMP_PN_LEN 6
#define NUM_RX_DATA_QUEUES 17
struct ieee80211_key {
struct kref kref;
int hw_key_idx; /* filled and used by low-level driver */
ieee80211_key_alg alg;
union {
struct {
/* last used TSC */
u32 iv32;
u16 iv16;
u16 p1k[5];
int tx_initialized;
/* last received RSC */
u32 iv32_rx[NUM_RX_DATA_QUEUES];
u16 iv16_rx[NUM_RX_DATA_QUEUES];
u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
int rx_initialized[NUM_RX_DATA_QUEUES];
} tkip;
struct {
u8 tx_pn[6];
u8 rx_pn[NUM_RX_DATA_QUEUES][6];
struct crypto_cipher *tfm;
u32 replays; /* dot11RSNAStatsCCMPReplays */
/* scratch buffers for virt_to_page() (crypto API) */
#ifndef AES_BLOCK_LEN
#define AES_BLOCK_LEN 16
#endif
u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
} ccmp;
} u;
int tx_rx_count; /* number of times this key has been used */
int keylen;
/* if the low level driver can provide hardware acceleration it should
* clear this flag */
unsigned int force_sw_encrypt:1;
unsigned int default_tx_key:1; /* This key is the new default TX key
* (used only for broadcast keys). */
s8 keyidx; /* WEP key index */
#ifdef CONFIG_MAC80211_DEBUGFS
struct {
struct dentry *stalink;
struct dentry *dir;
struct dentry *keylen;
struct dentry *force_sw_encrypt;
struct dentry *keyidx;
struct dentry *hw_key_idx;
struct dentry *tx_rx_count;
struct dentry *algorithm;
struct dentry *tx_spec;
struct dentry *rx_spec;
struct dentry *replays;
struct dentry *key;
} debugfs;
#endif
u8 key[0];
};
#endif /* IEEE80211_KEY_H */
/*
* Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/* just for IFNAMSIZ */
#include <linux/if.h>
#include "ieee80211_led.h"
void ieee80211_led_rx(struct ieee80211_local *local)
{
if (unlikely(!local->rx_led))
return;
if (local->rx_led_counter++ % 2 == 0)
led_trigger_event(local->rx_led, LED_OFF);
else
led_trigger_event(local->rx_led, LED_FULL);
}
/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
void ieee80211_led_tx(struct ieee80211_local *local, int q)
{
if (unlikely(!local->tx_led))
return;
/* not sure how this is supposed to work ... */
local->tx_led_counter += 2*q-1;
if (local->tx_led_counter % 2 == 0)
led_trigger_event(local->tx_led, LED_OFF);
else
led_trigger_event(local->tx_led, LED_FULL);
}
void ieee80211_led_init(struct ieee80211_local *local)
{
local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
if (!local->rx_led)
return;
snprintf(local->rx_led_name, sizeof(local->rx_led_name),
"%srx", wiphy_name(local->hw.wiphy));
local->rx_led->name = local->rx_led_name;
if (led_trigger_register(local->rx_led)) {
kfree(local->rx_led);
local->rx_led = NULL;
}
local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
if (!local->tx_led)
return;
snprintf(local->tx_led_name, sizeof(local->tx_led_name),
"%stx", wiphy_name(local->hw.wiphy));
local->tx_led->name = local->tx_led_name;
if (led_trigger_register(local->tx_led)) {
kfree(local->tx_led);
local->tx_led = NULL;
}
}
void ieee80211_led_exit(struct ieee80211_local *local)
{
if (local->tx_led) {
led_trigger_unregister(local->tx_led);
kfree(local->tx_led);
}
if (local->rx_led) {
led_trigger_unregister(local->rx_led);
kfree(local->rx_led);
}
}
char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
if (local->tx_led)
return local->tx_led_name;
return NULL;
}
EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
if (local->rx_led)
return local->rx_led_name;
return NULL;
}
EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
/*
* Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/leds.h>
#include "ieee80211_i.h"
#ifdef CONFIG_MAC80211_LEDS
extern void ieee80211_led_rx(struct ieee80211_local *local);
extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
extern void ieee80211_led_init(struct ieee80211_local *local);
extern void ieee80211_led_exit(struct ieee80211_local *local);
#else
static inline void ieee80211_led_rx(struct ieee80211_local *local)
{
}
static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
{
}
static inline void ieee80211_led_init(struct ieee80211_local *local)
{
}
static inline void ieee80211_led_exit(struct ieee80211_local *local)
{
}
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* Michael MIC implementation - optimized for TKIP MIC operations
* Copyright 2002-2003, Instant802 Networks, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef MICHAEL_H
#define MICHAEL_H
#include <linux/types.h>
#define MICHAEL_MIC_LEN 8
void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority,
u8 *data, size_t data_len, u8 *mic);
#endif /* MICHAEL_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* Copyright 2002-2004, Instant802 Networks, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef TKIP_H
#define TKIP_H
#include <linux/types.h>
#include <linux/crypto.h>
#include "ieee80211_key.h"
u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
u8 iv0, u8 iv1, u8 iv2);
void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta,
u16 *phase1key);
void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
u8 *rc4key);
void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
struct ieee80211_key *key,
u8 *pos, size_t payload_len, u8 *ta);
enum {
TKIP_DECRYPT_OK = 0,
TKIP_DECRYPT_NO_EXT_IV = -1,
TKIP_DECRYPT_INVALID_KEYIDX = -2,
TKIP_DECRYPT_REPLAY = -3,
};
int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
struct ieee80211_key *key,
u8 *payload, size_t payload_len, u8 *ta,
int only_iv, int queue);
#endif /* TKIP_H */
此差异已折叠。
/*
* Software WEP encryption implementation
* Copyright 2002, Jouni Malinen <jkmaline@cc.hut.fi>
* Copyright 2003, Instant802 Networks, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef WEP_H
#define WEP_H
#include <linux/skbuff.h>
#include <linux/types.h>
#include "ieee80211_i.h"
#include "ieee80211_key.h"
int ieee80211_wep_init(struct ieee80211_local *local);
void ieee80211_wep_free(struct ieee80211_local *local);
void ieee80211_wep_get_iv(struct ieee80211_local *local,
struct ieee80211_key *key, u8 *iv);
u8 * ieee80211_wep_add_iv(struct ieee80211_local *local,
struct sk_buff *skb,
struct ieee80211_key *key);
void ieee80211_wep_remove_iv(struct ieee80211_local *local,
struct sk_buff *skb,
struct ieee80211_key *key);
void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
size_t klen, u8 *data, size_t data_len);
int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
size_t klen, u8 *data, size_t data_len);
int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
struct ieee80211_key *key);
int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
struct ieee80211_key *key);
int ieee80211_wep_get_keyidx(struct sk_buff *skb);
u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
#endif /* WEP_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册