Release 4.11 drivers/staging/wilc1000/linux_mon.c
/*!
* @file linux_mon.c
* @brief File Operations OS wrapper functionality
* @author mdaftedar
* @sa wilc_wfi_netdevice.h
* @date 01 MAR 2012
* @version 1.0
*/
#include "wilc_wfi_cfgoperations.h"
#include "wilc_wlan_if.h"
#include "wilc_wlan.h"
struct wilc_wfi_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
u8 rate;
}
__packed;
struct wilc_wfi_radiotap_cb_hdr {
struct ieee80211_radiotap_header hdr;
u8 rate;
u8 dump;
u16 tx_flags;
}
__packed;
static struct net_device *wilc_wfi_mon;
/* global monitor netdev */
static u8 srcadd[6];
static u8 bssid[6];
static u8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
/**
* @brief WILC_WFI_monitor_rx
* @details
* @param[in]
* @return int : Return 0 on Success
* @author mdaftedar
* @date 12 JUL 2012
* @version 1.0
*/
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004
/* used rts/cts handshake */
#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001
/* failed due to excessive*/
#define IS_MANAGMEMENT 0x100
#define IS_MANAGMEMENT_CALLBACK 0x080
#define IS_MGMT_STATUS_SUCCES 0x040
#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
void WILC_WFI_monitor_rx(u8 *buff, u32 size)
{
u32 header, pkt_offset;
struct sk_buff *skb = NULL;
struct wilc_wfi_radiotap_hdr *hdr;
struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
if (!wilc_wfi_mon)
return;
if (!netif_running(wilc_wfi_mon))
return;
/* Get WILC header */
memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
/*
* The packet offset field contain info about what type of management
* the frame we are dealing with and ack status
*/
pkt_offset = GET_PKT_OFFSET(header);
if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
/* hostapd callback mgmt frame */
skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr));
if (!skb)
return;
memcpy(skb_put(skb, size), buff, size);
cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb, sizeof(*cb_hdr));
memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
cb_hdr->hdr.it_present = cpu_to_le32(
(1 << IEEE80211_RADIOTAP_RATE) |
(1 << IEEE80211_RADIOTAP_TX_FLAGS));
cb_hdr->rate = 5; /* txrate->bitrate / 5; */
if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
/* success */
cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS;
} else {
cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL;
}
} else {
skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr));
if (!skb)
return;
memcpy(skb_put(skb, size), buff, size);
hdr = (struct wilc_wfi_radiotap_hdr *)skb_push(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr));
hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr));
hdr->hdr.it_present = cpu_to_le32
(1 << IEEE80211_RADIOTAP_RATE); /* | */
hdr->rate = 5; /* txrate->bitrate / 5; */
}
skb->dev = wilc_wfi_mon;
skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = htons(ETH_P_802_2);
memset(skb->cb, 0, sizeof(skb->cb));
netif_rx(skb);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johnny Kim | 378 | 97.93% | 1 | 16.67% |
Chaehyun Lim | 6 | 1.55% | 3 | 50.00% |
Anchal Jain | 1 | 0.26% | 1 | 16.67% |
Zhang Shengju | 1 | 0.26% | 1 | 16.67% |
Total | 386 | 100.00% | 6 | 100.00% |
struct tx_complete_mon_data {
int size;
void *buff;
};
static void mgmt_tx_complete(void *priv, int status)
{
struct tx_complete_mon_data *pv_data = priv;
/*
* in case of fully hosting mode, the freeing will be done
* in response to the cfg packet
*/
kfree(pv_data->buff);
kfree(pv_data);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johnny Kim | 32 | 96.97% | 1 | 50.00% |
Anchal Jain | 1 | 3.03% | 1 | 50.00% |
Total | 33 | 100.00% | 2 | 100.00% |
static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
{
struct tx_complete_mon_data *mgmt_tx = NULL;
if (!dev)
return -EFAULT;
netif_stop_queue(dev);
mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC);
if (!mgmt_tx)
return -ENOMEM;
mgmt_tx->buff = kmalloc(len, GFP_ATOMIC);
if (!mgmt_tx->buff) {
kfree(mgmt_tx);
return -ENOMEM;
}
mgmt_tx->size = len;
memcpy(mgmt_tx->buff, buf, len);
wilc_wlan_txq_add_mgmt_pkt(dev, mgmt_tx, mgmt_tx->buff, mgmt_tx->size,
mgmt_tx_complete);
netif_wake_queue(dev);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johnny Kim | 114 | 85.71% | 1 | 12.50% |
Chaehyun Lim | 7 | 5.26% | 3 | 37.50% |
Tony Cho | 5 | 3.76% | 1 | 12.50% |
Leo Kim | 4 | 3.01% | 1 | 12.50% |
Glen Lee | 3 | 2.26% | 2 | 25.00% |
Total | 133 | 100.00% | 8 | 100.00% |
/**
* @brief WILC_WFI_mon_xmit
* @details
* @param[in]
* @return int : Return 0 on Success
* @author mdaftedar
* @date 12 JUL 2012
* @version 1.0
*/
static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
struct net_device *dev)
{
u32 rtap_len, ret = 0;
struct WILC_WFI_mon_priv *mon_priv;
struct sk_buff *skb2;
struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
if (!wilc_wfi_mon)
return -EFAULT;
mon_priv = netdev_priv(wilc_wfi_mon);
if (!mon_priv)
return -EFAULT;
rtap_len = ieee80211_get_radiotap_len(skb->data);
if (skb->len < rtap_len)
return -1;
skb_pull(skb, rtap_len);
if (skb->data[0] == 0xc0 && (!(memcmp(broadcast, &skb->data[4], 6)))) {
skb2 = dev_alloc_skb(skb->len + sizeof(struct wilc_wfi_radiotap_cb_hdr));
memcpy(skb_put(skb2, skb->len), skb->data, skb->len);
cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb2, sizeof(*cb_hdr));
memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
cb_hdr->hdr.it_present = cpu_to_le32(
(1 << IEEE80211_RADIOTAP_RATE) |
(1 << IEEE80211_RADIOTAP_TX_FLAGS));
cb_hdr->rate = 5; /* txrate->bitrate / 5; */
cb_hdr->tx_flags = 0x0004;
skb2->dev = wilc_wfi_mon;
skb_reset_mac_header(skb2);
skb2->ip_summed = CHECKSUM_UNNECESSARY;
skb2->pkt_type = PACKET_OTHERHOST;
skb2->protocol = htons(ETH_P_802_2);
memset(skb2->cb, 0, sizeof(skb2->cb));
netif_rx(skb2);
return 0;
}
skb->dev = mon_priv->real_ndev;
/* Identify if Ethernet or MAC header (data or mgmt) */
memcpy(srcadd, &skb->data[10], 6);
memcpy(bssid, &skb->data[16], 6);
/* if source address and bssid fields are equal>>Mac header */
/*send it to mgmt frames handler */
if (!(memcmp(srcadd, bssid, 6))) {
ret = mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len);
if (ret)
netdev_err(dev, "fail to mgmt tx\n");
dev_kfree_skb(skb);
} else {
ret = wilc_mac_xmit(skb, mon_priv->real_ndev);
}
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johnny Kim | 385 | 93.67% | 1 | 11.11% |
Leo Kim | 17 | 4.14% | 2 | 22.22% |
Chaehyun Lim | 5 | 1.22% | 3 | 33.33% |
Anchal Jain | 2 | 0.49% | 1 | 11.11% |
Zhang Shengju | 1 | 0.24% | 1 | 11.11% |
Arnd Bergmann | 1 | 0.24% | 1 | 11.11% |
Total | 411 | 100.00% | 9 | 100.00% |
static const struct net_device_ops wilc_wfi_netdev_ops = {
.ndo_start_xmit = WILC_WFI_mon_xmit,
};
/**
* @brief WILC_WFI_init_mon_interface
* @details
* @param[in]
* @return int : Return 0 on Success
* @author mdaftedar
* @date 12 JUL 2012
* @version 1.0
*/
struct net_device *WILC_WFI_init_mon_interface(const char *name,
struct net_device *real_dev)
{
u32 ret = 0;
struct WILC_WFI_mon_priv *priv;
/*If monitor interface is already initialized, return it*/
if (wilc_wfi_mon)
return wilc_wfi_mon;
wilc_wfi_mon = alloc_etherdev(sizeof(struct WILC_WFI_mon_priv));
if (!wilc_wfi_mon)
return NULL;
wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP;
strncpy(wilc_wfi_mon->name, name, IFNAMSIZ);
wilc_wfi_mon->name[IFNAMSIZ - 1] = 0;
wilc_wfi_mon->netdev_ops = &wilc_wfi_netdev_ops;
ret = register_netdevice(wilc_wfi_mon);
if (ret) {
netdev_err(real_dev, "register_netdevice failed\n");
return NULL;
}
priv = netdev_priv(wilc_wfi_mon);
if (!priv)
return NULL;
priv->real_ndev = real_dev;
return wilc_wfi_mon;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johnny Kim | 129 | 94.85% | 1 | 16.67% |
Leo Kim | 4 | 2.94% | 2 | 33.33% |
Chaehyun Lim | 2 | 1.47% | 2 | 33.33% |
Arnd Bergmann | 1 | 0.74% | 1 | 16.67% |
Total | 136 | 100.00% | 6 | 100.00% |
/**
* @brief WILC_WFI_deinit_mon_interface
* @details
* @param[in]
* @return int : Return 0 on Success
* @author mdaftedar
* @date 12 JUL 2012
* @version 1.0
*/
int WILC_WFI_deinit_mon_interface(void)
{
bool rollback_lock = false;
if (wilc_wfi_mon) {
if (rtnl_is_locked()) {
rtnl_unlock();
rollback_lock = true;
}
unregister_netdev(wilc_wfi_mon);
if (rollback_lock) {
rtnl_lock();
rollback_lock = false;
}
wilc_wfi_mon = NULL;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johnny Kim | 53 | 92.98% | 1 | 33.33% |
Chandra S Gorentla | 3 | 5.26% | 1 | 33.33% |
Leo Kim | 1 | 1.75% | 1 | 33.33% |
Total | 57 | 100.00% | 3 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Johnny Kim | 1222 | 94.29% | 1 | 4.35% |
Leo Kim | 26 | 2.01% | 3 | 13.04% |
Chaehyun Lim | 22 | 1.70% | 8 | 34.78% |
Arnd Bergmann | 5 | 0.39% | 3 | 13.04% |
Tony Cho | 5 | 0.39% | 1 | 4.35% |
Anchal Jain | 5 | 0.39% | 2 | 8.70% |
Glen Lee | 3 | 0.23% | 2 | 8.70% |
Chandra S Gorentla | 3 | 0.23% | 1 | 4.35% |
Greg Kroah-Hartman | 3 | 0.23% | 1 | 4.35% |
Zhang Shengju | 2 | 0.15% | 1 | 4.35% |
Total | 1296 | 100.00% | 23 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.